采用Matrix实现图片查看

来源:互联网 发布:agv磁条算法 编辑:程序博客网 时间:2024/06/05 20:41

 本文是采用重写ImgView实现图片放大,缩放,移动,裁剪,

   

package com.example.app.view;import android.content.Context;import android.graphics.Matrix;import android.graphics.RectF;import android.graphics.drawable.Drawable;import android.util.AttributeSet;import android.util.Log;import android.view.GestureDetector;import android.view.MotionEvent;import android.view.ScaleGestureDetector;import android.view.View;import android.view.ViewConfiguration;import android.view.ViewTreeObserver;import android.widget.ImageView;/** * Created by User on 2015/12/13. */public class ZoomImageView extends ImageView implements ViewTreeObserver.OnGlobalLayoutListener,        ScaleGestureDetector.OnScaleGestureListener, View.OnTouchListener {    private boolean mOnce = false;    /**     * 初始化时缩放的值     */    private float mInitScale;    //private float minInitScale;    /**     * 双击放大值到达的值     */    private float mMidScale;    /**     * 放大的大值到达的值     */    private float mMaxScale;    /**     * 捕获用户多指触控是缩放的比例     */    private ScaleGestureDetector scaleGestureDetector;    private Matrix mScaleMatrix;    //----------自由移动    /**     * 记录上一次多点触控的数量     */    private int mLastPointerCount;    private float mLastX;    private float mLastY;    private int mTouchSlop;    private boolean isCanDrag;    private RectF matrixRectF;    private boolean isCheckLeftAndRight;    private boolean isCheckTopAndBottom;    /**     * 双击放大与缩小——————————————————————————     */    private GestureDetector mGestureDetector;    private boolean isAutoScale;    public ZoomImageView(Context context) {        this(context, null);    }    public ZoomImageView(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public ZoomImageView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        mScaleMatrix = new Matrix();        super.setScaleType(ScaleType.MATRIX);        scaleGestureDetector = new ScaleGestureDetector(context, this);        mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {            @Override            public boolean onDoubleTap(MotionEvent e) {                if (isAutoScale) {                    return true;                }                float x = e.getX();                float y = e.getY();                if (getScale() < mMidScale) {//                    mScaleMatrix.postScale(mMidScale / getScale(), mMidScale / getScale(), x, y);//                    setImageMatrix(mScaleMatrix);                    postDelayed(new AutoScaleRunnable(mMidScale, x, y), 16);                    isAutoScale = true;                } else {//                    mScaleMatrix.postScale(mInitScale / getScale(), mInitScale / getScale(), x, y);//                    setImageMatrix(mScaleMatrix);                    postDelayed(new AutoScaleRunnable(mInitScale, x, y), 16);                    isAutoScale = true;                }                return true;            }        });        this.setOnTouchListener(this);        //判断是否是移动        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();    }    private class AutoScaleRunnable implements Runnable {        /**         * 缩放的目标         */        private float mTargetScale;        //缩放的中心        private float x;        private float y;        private final float BIGGER = 1.07f;        private final float SMALL = 0.93f;        private float tmpScale;        public AutoScaleRunnable(float mTargetScale, float x, float y) {            this.mTargetScale = mTargetScale;            this.x = x;            this.y = y;            if (getScale() < mTargetScale) {                tmpScale = BIGGER;            }            if (getScale() > mTargetScale) {                tmpScale = SMALL;            }        }        @Override        public void run() {            //进行缩放            mScaleMatrix.postScale(tmpScale, tmpScale, x, y);            ckecheBorderAndCenterWhenScale();            setImageMatrix(mScaleMatrix);            float currentScale = getScale();            if ((tmpScale > 1.0f && currentScale < mTargetScale) || (tmpScale < 1.0f && currentScale > mTargetScale)) {                postDelayed(this, 16);            } else {                //设置为目标值                float scale = mTargetScale / currentScale;                mScaleMatrix.postScale(scale, scale, x, y);                ckecheBorderAndCenterWhenScale();                setImageMatrix(mScaleMatrix);                isAutoScale = false;            }        }    }    @Override    protected void onAttachedToWindow() {        super.onAttachedToWindow();        //添加        getViewTreeObserver().addOnGlobalLayoutListener(this);    }    @Override    protected void onDetachedFromWindow() {        super.onDetachedFromWindow();        //删除        getViewTreeObserver().removeGlobalOnLayoutListener(this);    }    /**     * 获取ImageView加载完成的图片     */    @Override    public void onGlobalLayout() {        if (!mOnce) {            //得到控件的宽和高            int width = getWidth();            int height = getHeight();            //得到我们的图片,以及宽和高            Drawable drawable = getDrawable();            if (drawable == null) {                return;            }            int drawableWidth = drawable.getIntrinsicWidth();            int drawableHeight = drawable.getIntrinsicHeight();            float scale = 1.0f;            float minScale = 1.0f;            /**             * 如果图片的宽度大于控件宽度,但是高度小于控件宽度,我们将其放大、             * */            if (drawableWidth > width && drawableHeight < height) {                scale = width * 1.0f / drawableWidth;            }            /**             * 如果图片的高度于控件高度,但是宽度小于控件宽度,我们将其缩小、             * */            if (drawableHeight > height && drawableWidth < width) {                scale = height * 1.0f / drawableHeight;            }            /**             * 如果图片的宽高都大于控件,我们将其缩小,。             * */            if (drawableWidth > width && drawableHeight > height) {                scale = Math.min(width * 1.0f / drawableWidth, height * 1.0f / drawableHeight);            }            /**             * 如果图片的宽高都小于控件,我们将其放大。             * */            if (drawableWidth < width && drawableHeight < height) {                scale = Math.min(width * 1.0f / drawableWidth, height * 1.0f / drawableHeight);            }            /**             * 得到了初始化时缩放的比例             * */            mInitScale = scale;            mMaxScale = mInitScale * 4;            mMidScale = mInitScale * 2;            //   minInitScale = minScale;            mOnce = true;            /**             * 将图片移动至控件的中心             * */            int dx = getWidth() / 2 - drawableWidth / 2;            int dy = getHeight() / 2 - drawableHeight / 2;            mScaleMatrix.postTranslate(dx, dy);            mScaleMatrix.postScale(mInitScale, mInitScale, width / 2, height / 2);            setImageMatrix(mScaleMatrix);        }    }    //缩放的区间:initScale,MaxScale    //获取图片当前的缩放值    public float getScale() {        float[] values = new float[9];        mScaleMatrix.getValues(values);        return values[Matrix.MSCALE_X];    }    @Override    public boolean onScale(ScaleGestureDetector detector) {        float scale = getScale();        //获得当前的缩放值        float scaleFactor = detector.getScaleFactor();        Log.d("scaleFactor", ":" + scaleFactor);        if (getDrawable() == null) {            return true;        }        //缩放范围的控制        if ((scale < mMaxScale && scaleFactor > 1.0f) ||                (scale > mInitScale && scaleFactor < 1.0f)) {            if (scale * scaleFactor < mInitScale) {                scaleFactor = mInitScale / scale;            }            if (scale * scaleFactor > mMaxScale) {                scaleFactor = mMaxScale / scale;            }            mScaleMatrix.postScale(scaleFactor, scaleFactor, detector.getFocusX(), detector.getFocusY());            ckecheBorderAndCenterWhenScale();            setImageMatrix(mScaleMatrix);        }        return true;    }    /**     * 获得图片放大缩小以后的宽和高,以及l,r,t,b     */    private RectF getMatrixRectF() {        Matrix rMatrix = mScaleMatrix;        RectF rectF = new RectF();        Drawable d = getDrawable();        if (d != null) {            rectF.set(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());            rMatrix.mapRect(rectF);        }        return rectF;    }    /**     * 再缩放的时候进行边界控制已经我们的位置的控制     */    private void ckecheBorderAndCenterWhenScale() {        RectF rect = getMatrixRectF();        float deltaX = 0;        float deltaY = 0;        int width = getWidth();        int height = getHeight();        if (rect.width() >= width) {            if (rect.left > 0) {                deltaX = -rect.left;            }            if (rect.right < width) {                deltaX = width - rect.right;            }        }        if (rect.height() >= height) {            if (rect.top > 0) {                deltaY = -rect.top;            }            if (rect.bottom < height) {                deltaY = height - rect.bottom;            }        }        /**         * 如果宽度或者高度小于控件的宽或者高;则让其居中         *         * */        if (rect.width() < width) {            deltaX = width * 0.5f - rect.right + 0.5f * rect.width();        }        if (rect.height() < height) {            deltaY = height * 0.5f - rect.bottom + 0.5f * rect.height();        }        mScaleMatrix.postTranslate(deltaX, deltaY);    }    @Override    public boolean onScaleBegin(ScaleGestureDetector detector) {        return true;    }    @Override    public void onScaleEnd(ScaleGestureDetector detector) {    }    @Override    public boolean onTouch(View v, MotionEvent event) {        if (mGestureDetector.onTouchEvent(event)) {            return true;        }        scaleGestureDetector.onTouchEvent(event);        float X = 0;        float Y = 0;        /**         * 拿到多点触控的数量         * */        int pointerCount = event.getPointerCount();        for (int i = 0; i < pointerCount; i++) {            X += event.getX(i);            Y += event.getY(i);        }        X /= pointerCount;        Y /= pointerCount;        if (mLastPointerCount != pointerCount) {            mLastX = X;            mLastY = Y;        }        mLastPointerCount = pointerCount;        switch (event.getAction()) {            case MotionEvent.ACTION_MOVE:                float dx = X - mLastX;                float dy = Y - mLastY;                if (!isCanDrag) {                    isCanDrag = isMoveAction(dx, dy);                }                if (isCanDrag) {                    RectF rectF = getMatrixRectF();                    if (getDrawable() != null) {                        isCheckLeftAndRight = isCheckTopAndBottom = true;                        /**                         * 如果宽度小于控件宽度,不允许横向移动                         * */                        if (rectF.width() < getWidth()) {                            isCheckLeftAndRight = false;                            dx = 0;                        }                        /**                         * 如果高度小于控件高度,不允许纵向移动                         * */                        if (rectF.height() < getHeight()) {                            isCheckTopAndBottom = false;                            dy = 0;                        }                        mScaleMatrix.postTranslate(dx, dy);                        checkBorderWhenTranslate();                        setImageMatrix(mScaleMatrix);                    }                }                mLastX = X;                mLastY = Y;                break;            case MotionEvent.ACTION_UP:            case MotionEvent.ACTION_CANCEL:                mLastPointerCount = 0;                break;        }        return true;    }    /**     * 当移动,进行边界检查     */    private void checkBorderWhenTranslate() {        RectF rectF = getMatrixRectF();        float deltaX = 0;        float deltaY = 0;        int width = getWidth();        int height = getHeight();        if (rectF.top > 0 && isCheckTopAndBottom) {            deltaY = -rectF.top;        }        if (rectF.bottom < height && isCheckTopAndBottom) {            deltaY = height - rectF.bottom;        }        if (rectF.left > 0 && isCheckLeftAndRight) {            deltaX = -rectF.left;        }        if (rectF.right < width && isCheckLeftAndRight) {            deltaX = width - rectF.right;        }        mScaleMatrix.postTranslate(deltaX, deltaY);    }    /**     * 判断是否是Move     */    private boolean isMoveAction(float dx, float dy) {        return Math.sqrt(dx * dx + dy * dy) > mTouchS     }    /**     * 剪切图片,返回剪切后的bitmap对象 圆形用     *     * @return     */    public Bitmap clip() {        Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(),                Bitmap.Config.ARGB_8888);        Canvas canvas = new Canvas(bitmap);        int yStartPoint = DensityUtils.dp2px(getContext(), (float) 135.333);        int xStartPoint = DensityUtils.dp2px(getContext(), (float) 62);        int circleRadius = DensityUtils.dp2px(getContext(), (float) 236);        draw(canvas);        return Bitmap.createBitmap(bitmap, xStartPoint,                yStartPoint, circleRadius,                circleRadius);    }}


0 0
原创粉丝点击