为了账号安全,请及时绑定邮箱和手机立即绑定

打造个性的图片预览与多点触控

标签:
Android

自己动手敲出来的代码,很是不易,留备后用:

package com.view;

import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.AttributeSet;
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;
import android.view.View.OnTouchListener;
/**
 * Created by maybe on 2016/6/7.
 */
public class ZoomImageView extends ImageView implements ViewTreeObserver.OnGlobalLayoutListener,
        ScaleGestureDetector.OnScaleGestureListener, View.OnTouchListener {

    private boolean mOnce;

    private float mInitScale;
    private float mMidScale;
    private float mMaxScale;

    private Matrix mScaleMatrix;

    private ScaleGestureDetector mScaleGestureDetector;

    //--------------------------自由移动
    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;

    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();
        setScaleType(ScaleType.MATRIX);

        mScaleGestureDetector = new ScaleGestureDetector(context,this);
        setOnTouchListener(this);

        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();

        mGestureDetector = new GestureDetector(context,
                new GestureDetector.SimpleOnGestureListener(){
                    @Override
                    public boolean onDoubleTap(MotionEvent e) {
                        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);
                            boolean isAutoScale = true;
                        }
                        else
                        {
//                            mScaleMatrix.postScale(mInitScale/getScale(),mInitScale/getScale(),x,y);
//                            setImageMatrix(mScaleMatrix);
                            postDelayed(new AutoScaleRunnable(mInitScale,x,y),16);
                            boolean isAutoScale = true;
                        }
                        return true;
                    }
                });
    }

    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);
            checkBorderAndCenterWhenScale();
            setImageMatrix(mScaleMatrix);

            float currentScalel = getScale();

            if((tmpScale > 1.0f && currentScalel < mTargetScale)||
                    (tmpScale < 1.0f && currentScalel > mTargetScale))
            {
                postDelayed(this,16);
            }
            else
            {
                float Scale = mTargetScale/currentScalel;
                mScaleMatrix.postScale(Scale,Scale,x,y);
                checkBorderAndCenterWhenScale();
                setImageMatrix(mScaleMatrix);
            }
        }
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();

        getViewTreeObserver().addOnGlobalLayoutListener(this);
    }

    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        getViewTreeObserver().removeOnGlobalLayoutListener(this);
    }

    @Override
    public void onGlobalLayout() {
        if(!mOnce)
        {
            int width = getWidth();
            int height = getHeight();

            Drawable d = getDrawable();
            if(d == null)
                return;

            int dw = d.getIntrinsicWidth();
            int dh = d.getIntrinsicHeight();

            float scale = 1.0f;

            if(dw > width && dh < height)
            {
                scale = width * 1.0f/dw;
            }

            if(dh > height && dw < width)
            {
                scale = height*1.0f/dh;
            }

            if((dw > width && dh > height)||(dw < width && dh < height))
            {
                scale = Math.min(width * 1.0f/dw,height*1.0f/dw);
            }

            mInitScale = scale;
            mMidScale = mInitScale *2;
            mMaxScale = mInitScale *4;

            int dx = getWidth()/2 - dw/2;
            int dy = getHeight()/2 - dh/2;

            mScaleMatrix.postTranslate(dx,dy);//移动到中心位置
            mScaleMatrix.postScale(mInitScale,mInitScale,
                    mScaleGestureDetector.getFocusX(),mScaleGestureDetector.getFocusY());

            checkBorderAndCenterWhenScale();

            setImageMatrix(mScaleMatrix); //完成平移缩放

            mOnce = true;
        }
    }

    private RectF getMatrixRectf()//获得缩放后的宽高及个点坐标
    {
        Matrix matrix = mScaleMatrix;
        RectF rectf = new RectF();

        Drawable d = getDrawable();
        if(d != null)
        {
            rectf.set(0,0,d.getIntrinsicWidth(),d.getIntrinsicHeight());
            matrix.mapRect(rectf);
        }
        return rectf;
    }

    private void checkBorderAndCenterWhenScale() {
        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/2f - rect.right + rect.width()/2f;
        }

        if(rect.height() < height)
        {
            deltaY = height/2f - rect.bottom + rect.height()/2f;
        }

        mScaleMatrix.postTranslate(deltaX,deltaY);
    }

    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();
        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)
            {
                scale = mMaxScale/scale;
            }

            mScaleMatrix.postScale(scaleFactor,scaleFactor,getWidth()/2,getHeight()/2);
            setImageMatrix(mScaleMatrix);
        }
        return true;
    }

    @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;
        }

        mScaleGestureDetector.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)
        {
            isCanDrag = false;
            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;
            default:
        }
        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);

    }

    private boolean isMoveAction(float dx, float dy) {
        return Math.sqrt(dx*dx + dy*dy) > mTouchSlop;
    }
}

ZoomImageView.java 文件,实现图片的放大缩小,移动,以及双击放大缩小!

点击查看更多内容
8人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消