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的地址,今天這資源我是傳不上去了。

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章