1. 程式人生 > >Android 點選圖片放大展示 展示中可調節圖片的縮放顯示 圖片檢視器

Android 點選圖片放大展示 展示中可調節圖片的縮放顯示 圖片檢視器

1.首先需要初始化一個全域性常量

這個是常量的工具類

public final class GlobalConstant {

    private static int DEVICE_WIDTH;
    private static int DEVICE_HEIGHT;
    private static float DEVICE_DENSITY;

    public static void initDeviceInfo(Context context) {
        WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics metrics = new
DisplayMetrics(); manager.getDefaultDisplay().getMetrics(metrics); DEVICE_WIDTH = metrics.widthPixels; DEVICE_HEIGHT = metrics.heightPixels; DEVICE_DENSITY = metrics.density; } public static int getDeviceWidth() { return DEVICE_WIDTH; } public
static int getDeviceHeight() { return DEVICE_HEIGHT; } public static float getDeviceDensity() { return DEVICE_DENSITY; } }

初始化的方法就是在程式的Application類對的oncreat方法中執行

 GlobalConstant.initDeviceInfo(this);

2.可縮放的ImageView

public class GestureImageView extends ImageView
implements ViewTreeObserver.OnGlobalLayoutListener {
private static final String TAG = GestureImageView.class.getSimpleName(); private boolean isOnce = true; //初始縮放值 private float currentScale; private static int mWidth = GlobalConstant.getDeviceWidth(); private static int mHeight = GlobalConstant.getDeviceHeight(); private static int mDistance = (int) Math.sqrt((Math.pow(mWidth, 2) + Math.pow(mHeight, 2))); private final float MAX_SCALE = 4.0f; // 修改這個值可以修改縮放最大值 private float MIN_SCALE; private float[] mMatrixValues = new float[9]; private float[] initMatrixValues = new float[9]; private Matrix mMatrix = new Matrix(); private PointF scalePointF; private PointF dragPointF; private float preDistance = 0; private static final int SCALE_RATE = 4;//修改此值用以修改縮放速率 public GestureImageView(Context context) { super(context); initImageAttribute(); } public GestureImageView(Context context, AttributeSet attrs) { super(context, attrs); initImageAttribute(); } public GestureImageView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initImageAttribute(); } /** * 初始化影象屬性 */ private void initImageAttribute() { setScaleType(ScaleType.MATRIX); setFocusable(true);// 觸控事件開啟此引數用以搞事情 catchTouchEvent(true); } /** * 是否捕獲touch事件 * * @param flag true捕獲touch事件,false不捕獲 */ public void catchTouchEvent(boolean flag) { if (getParent() != null) { getParent().requestDisallowInterceptTouchEvent(flag); } } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); getViewTreeObserver().addOnGlobalLayoutListener(this); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { getViewTreeObserver().removeOnGlobalLayoutListener(this); } else { getViewTreeObserver().addOnGlobalLayoutListener(null); } } @Override public void setImageResource(int resId) { super.setImageResource(resId); adjustImageMatrix(); } @Override public void setImageBitmap(Bitmap bm) { super.setImageBitmap(bm); adjustImageMatrix(); } @Override public boolean onTouchEvent(MotionEvent event) { int action = event.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: catchTouchEvent(true); scalePointF = null; preDistance = 0; dragPointF = null; break; case MotionEvent.ACTION_MOVE: if (event.getPointerCount() == 2) { //兩點觸控事件處理 handleScaleEvent(event); } if (event.getPointerCount() == 1) { //處理移動事件 handleDragEvent(event); } break; case MotionEvent.ACTION_POINTER_UP: if (event.getPointerCount() != 1) { scalePointF = null; preDistance = 0; dragPointF = null; } break; case MotionEvent.ACTION_UP: dragPointF = null; break; default: break; } return true; } /** * 處理拖拽手勢 * * @param event 觸控Event */ private void handleDragEvent(MotionEvent event) { scalePointF = null; if (dragPointF == null) { dragPointF = new PointF(event.getX(), event.getY()); } else { float x = event.getX(); float y = event.getY(); drag(x - dragPointF.x, y - dragPointF.y); dragPointF = new PointF(x, y); } } /** * 處理縮放手勢 * * @param event 事件 */ private void handleScaleEvent(MotionEvent event) { dragPointF = null; float fX = event.getX(0); float fY = event.getY(0); float sX = event.getX(1); float sY = event.getY(1); float distance = (float) Math.sqrt((Math.pow(fX - sX, 2) + Math.pow(fY - sY, 2))); if (scalePointF == null) { scalePointF = new PointF((fX + sX) / 2.0f, (fY + sY) / 2.0f); preDistance = distance; } else { float scale = (distance - preDistance) / mDistance * SCALE_RATE;//修改這個值可以更改縮放速率 float judge = currentScale + scale; scale = judge > MAX_SCALE || judge < MIN_SCALE ? (judge > MAX_SCALE ? MAX_SCALE - currentScale : MIN_SCALE - currentScale) : scale; currentScale += scale; scale(currentScale / (currentScale - scale), scalePointF); } preDistance = distance; } /** * 根據影象矩形處理拖拽的X值 * * @param rect 影象矩形 * @param dragX 拖拽的X值 * @return 處理以後dragX值 */ private float handleDragX(RectF rect, float dragX) { if (rect.left < 0 || rect.right > mWidth) { // 放大時,如果內容寬度大於螢幕,左右邊界不能出現黑邊 if (rect.left + dragX > 0) { dragX = 0 - rect.left; } else if (rect.right + dragX < mWidth) { dragX = mWidth - rect.right; } } else { dragX = 0; } return dragX; } /** * 根據影象矩形處理拖拽的Y值 * * @param rect 影象矩形 * @param dragY 拖拽的Y值 * @return 處理以後dragY值 */ private float handleDragY(RectF rect, float dragY) { if (rect.top <= 0 && rect.bottom >= mHeight) { // 放大時,如果內容寬度大於螢幕,左右邊界不能出現黑邊 if (rect.top + dragY > 0) { dragY = 0 - rect.top; } else if (rect.bottom + dragY < mHeight) { dragY = mHeight - rect.bottom; } } else { dragY = 0; } return dragY; } /** * 拖拽imageView * * @param dragX X軸的移動距離 * @param dragY Y軸的移動距離 */ private void drag(float dragX, float dragY) { RectF rect = getImageRectF(); catchTouchEvent(canDrag(rect)); dragX = handleDragX(rect, dragX); dragY = handleDragY(rect, dragY); mMatrix.postTranslate(dragX, dragY); setImageMatrix(mMatrix); mMatrix.getValues(mMatrixValues); } /** * 根據ImageView當前位置判斷是否可以拖拽 * * @param currentRect 當前的矩形 * @return true可以拖拽,false不可以 */ private boolean canDrag(RectF currentRect) { RectF preRect = getInitialRectF(); boolean canDrag; if (preRect.left > 0) { canDrag = !(currentRect.left >= 0 || currentRect.right <= mWidth || (currentRect.left > 0 && currentScale == MAX_SCALE)); } else { canDrag = !(currentRect.left == 0 || currentRect.right == mWidth); } return canDrag; } /** * 獲取初始的影象矩形 * * @return */ private RectF getInitialRectF() { Matrix preMatrix1 = new Matrix(); preMatrix1.setValues(initMatrixValues); return getImageRectF(preMatrix1); } /** * 縮放時,處理邊緣不過界 * * @param matrix 拷貝的矩陣 * @param scale 縮放比例 * @param f 縮放中心點 * @return 返回X座標的點 */ private float handleScaleDragX(Matrix matrix, float scale, PointF f) { matrix.postScale(scale, scale, f.x, mHeight / 2.0f); RectF rect = getImageRectF(matrix); // 根據拷貝過後的矩陣計算得出的矩形 RectF preRect = getInitialRectF(); float x = f.x; if (preRect.left > 0) { // 圖片初始矩形寬度小於螢幕寬度 x = rect.left > 0 || rect.right < mWidth ? mWidth / 2.0f : x; } else { x = rect.left > 0 ? 0 : (rect.right < mWidth ? mWidth : x); } return x; } /** * 按照縮放比例和點進行縮放 * * @param scale 縮放比例 * @param f 包含縮放中心點的PointF */ private void scale(float scale, PointF f) { LogUtil.showLog("縮放的比率:scale", scale+""); if (scale<=(float)1.00) { scale=(float) 1.00; } Matrix matrix = new Matrix(mMatrix); mMatrix.postScale(scale, scale, handleScaleDragX(matrix, scale, f), mHeight / 2.0f); mMatrix.getValues(mMatrixValues); // getImageRectF(); if (currentScale == MIN_SCALE) {// 縮放到初始位置,將圖片設定為初始位置,此處可以新增動畫,請隨意發揮。 mMatrix.setValues(initMatrixValues); setImageMatrix(mMatrix); } Log.i(TAG, "currentScale = " + currentScale); setImageMatrix(mMatrix); } /** * 將影象調整到適合的位置 */ private void adjustImageMatrix() { Drawable d = getDrawable(); if (d == null) { setImageResource(R.drawable.ic_launcher); return; } int width = d.getIntrinsicWidth(); int height = d.getIntrinsicHeight(); float scale = 1.0f; // 有3種情況,1、寬大於螢幕寬。2、高大於螢幕高。3、寬和高均大於螢幕,影象寬高均小於裝置的暫時不考慮 if (width > mWidth && height < mHeight) { scale = mWidth * 1.0f / width; } if (height > mHeight && width < mWidth) { scale = mHeight * 1.0f / height; } if (height > mHeight && width > mWidth) { scale = Math.min(mWidth * 1.0f / width, mHeight * 1.0f / height); } currentScale = scale; MIN_SCALE = scale; mMatrix = new Matrix(); mMatrix.postTranslate((mWidth - width) / 2.0f, (mHeight - height) / 2.0f); mMatrix.postScale(currentScale, currentScale, mWidth / 2.0f, mHeight / 2.0f); mMatrix.getValues(mMatrixValues); mMatrix.getValues(initMatrixValues); setImageMatrix(mMatrix); getImageRectF(); } /** * 返回Drawable的矩形 * * @param matrix 拷貝出來的矩陣 * @return imageView矩形資料 */ private RectF getImageRectF(Matrix matrix) { RectF rect = new RectF(); Drawable d = getDrawable(); if (d != null) { rect.set(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight()); matrix.mapRect(rect); } return rect; } /** * 返回Drawable的矩形 * * @return imageView矩形資料 */ private RectF getImageRectF() { RectF rect = new RectF(); Drawable d = getDrawable(); if (d != null) { rect.set(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight()); mMatrix.mapRect(rect); } return rect; } @Override public void onGlobalLayout() { if (isOnce) { isOnce = false; adjustImageMatrix(); } } }

3.用於展示圖片的Activity

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.view.View;
import android.view.ViewGroup.LayoutParams;

public class PhotoActivity extends Activity {

    private ArrayList<GestureImageView> listViews = null;
    private ViewPager pager;
    private MyPageAdapter adapter;

    public List<Bitmap> bmp = new ArrayList<Bitmap>();
    public int max;


    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_photo);


        for (int i = 0; i < Bimp.bmp.size(); i++) {
            bmp.add(Bimp.bmp.get(i));
        }
        max = Bimp.max;


        pager = (ViewPager) findViewById(R.id.viewpager);
        pager.setOnPageChangeListener(pageChangeListener);
        pager.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE);
        for (int i = 0; i < bmp.size(); i++) {
            initListViews(bmp.get(i));
        }

        adapter = new MyPageAdapter(listViews);// 構造adapter
        pager.setAdapter(adapter);// 設定介面卡
        Intent intent = getIntent();
        int id = intent.getIntExtra("ID", 0);
        pager.setCurrentItem(id);
    }

    @SuppressWarnings("deprecation")
    private void initListViews(Bitmap bm) {
        if (listViews == null)
            listViews = new ArrayList<GestureImageView>();
        GestureImageView img = new GestureImageView(this);// 構造textView物件
        img.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE);
        img.setBackgroundColor(0xff000000);
        img.setImageBitmap(bm);
        img.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
                LayoutParams.FILL_PARENT));
        listViews.add(img);// 新增view
    }

    private OnPageChangeListener pageChangeListener = new OnPageChangeListener() {

        public void onPageSelected(int arg0) {// 頁面選擇響應函式
        }

        public void onPageScrolled(int arg0, float arg1, int arg2) {// 滑動中。。。

        }

        public void onPageScrollStateChanged(int arg0) {// 滑動狀態改變

        }
    };

    class MyPageAdapter extends PagerAdapter {

        private ArrayList<GestureImageView> listViews;// content

        private int size;// 頁數

        public MyPageAdapter(ArrayList<GestureImageView> listViews) {// 建構函式
            // 初始化viewpager的時候給的一個頁面
            this.listViews = listViews;
            size = listViews == null ? 0 : listViews.size();
        }

        public void setListViews(ArrayList<GestureImageView> listViews) {// 自己寫的一個方法用來新增資料
            this.listViews = listViews;
            size = listViews == null ? 0 : listViews.size();
        }

        public int getCount() {// 返回數量
            return size;
        }

        public int getItemPosition(Object object) {
            return POSITION_NONE;
        }

        public void destroyItem(View arg0, int arg1, Object arg2) {// 銷燬view物件
            ((ViewPager) arg0).removeView(listViews.get(arg1 % size));
        }

        public void finishUpdate(View arg0) {
        }

        public Object instantiateItem(View arg0, int arg1) {// 返回view物件
            try {
                ((ViewPager) arg0).addView(listViews.get(arg1 % size), 0);

            } catch (Exception e) {
                LogUtil.showLogerror("執行instantiateItem方法時報錯:", e.toString());
            }
            return listViews.get(arg1 % size);
        }

        public boolean isViewFromObject(View arg0, Object arg1) {
            return arg0 == arg1;
        }

    }
}

此Activity的佈局檔案是:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    </android.support.v4.view.ViewPager>

</RelativeLayout>

4.主體都寫完了,接下來就是呼叫了

博主是這樣呼叫的。

Bitmap bm = Bimp.revitionImageSize(path);
//圖片的本地路徑
Bimp.bmp.add(bm);
Intent intent = new Intent(ctx,PhotoActivity.class);
intent.putExtra("ID", 0);
ctx.startActivity(intent);

後續,其實Bimp.bmp.add(bm);在這句程式碼裡再新增的時候,可以實現左右滑動來展示圖片,畢竟我們用的是ViewPager,但是博主在專案中展示的時候,需要實現微信的效果,還沒有構思出符合專案已有程式碼的邏輯,得加油啦。。。

5.此篇文章,我其實結合了在網上查詢的兩個Demo。

說什麼我都不能確定那兩個Demo的原始碼地址了,太對不起作者了,我已免費資源的方式放到這兩個網址中:

明天評論裡補這兩個Demo的地址,今天這資源我是傳不上去了。

這裡寫圖片描述