viewPager中的多点触控图片

慕课网hyman大神的课

出处:https://www.imooc.com/video/6729

可自由拖动、放大缩小、双击的ImageView

public class ZoomImgView 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 boolean isCheckLeftAndRight;

    private boolean isCheckTopAndBottom;

    //==================双击放大与缩小

    private GestureDetector mGestureDetector;

    private boolean isAutoScale;//双击后 正在处理双击变化的过程 就不处理双击事件了

    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 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);

                checkBorderAndCenterWhenScale();

                setImageMatrix(mScaleMatrix);

                isAutoScale =false;

            }

}

}

public ZoomImgView(Context context) {

this(context, null);

    }

public ZoomImgView(Context context, AttributeSet attrs) {

this(context, attrs, 0);

    }

public ZoomImgView(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) {

if (isAutoScale)

return true;

                float x = e.getX();

                float y = e.getY();

              if (getScale()

//                    mScaleMatrix.postScale(mMidScale / getScale(), mMidScale / getScale(), x, y);

//                    checkBorderAndCenterWhenScale();

//                    setImageMatrix(mScaleMatrix);

                    postDelayed(new AutoScaleRunnable(mMidScale, x, y), 16);

                    isAutoScale =true;

                }else {

//                    mScaleMatrix.postScale(mInitScale / getScale(), mInitScale / getScale(), x, y);

//                    checkBorderAndCenterWhenScale();

//                    setImageMatrix(mScaleMatrix);

                    postDelayed(new AutoScaleRunnable(mInitScale, x, y), 16);

                    isAutoScale =true;

                }

return true;

            }

});

    }

@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 drabWidth = drawable.getIntrinsicWidth();

            int drabHeight = drawable.getIntrinsicHeight();

            float scale =1.0f;

            //如果图片的宽度大于控件的宽度,但是图片的高度小于控件的高度,将其缩小

            if (drabWidth > width && drabHeight < height) {

scale = width *1.0f / drabWidth;

            }

//如果图片的高度大于控件的高度,但是图片的宽度小于控件的宽度,将其缩小

            if (drabHeight > height && drabWidth < width) {

scale = height *1.0f / drabHeight;

            }

//如果图片的宽高都大于控件的宽高或者宽高都小于控件的宽高,将其缩小/放大到合适的位置

            if (drabWidth > width && drabHeight > height) {

scale = Math.min(width *1.0f / drabWidth, height *1.0f / drabHeight);

            }

if (drabWidth < width && drabHeight < height) {

scale = Math.min(width *1.0f / drabWidth, height *1.0f / drabHeight);

            }

//得到初始化时的缩放比例

            mInitScale = scale;

            mMaxScale =mInitScale *4;

            mMidScale =mInitScale *2;

            //将图片移动至控件中心

            int dx = getWidth() /2 - drabWidth /2;

            int dy = getHeight() /2 - drabHeight /2;

            mScaleMatrix.postTranslate(dx, dy);

            mScaleMatrix.postScale(mInitScale, mInitScale, width /2, height /2);

            setImageMatrix(mScaleMatrix);

            mOnce =true;

        }

}

//获取当前图片的缩放值

    private 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 1.0f) || (scale >mInitScale && scaleFactor <1.0f)) {

if (scale * scaleFactor

scaleFactor =mInitScale / scale;

    }

if (scale * scaleFactor >mMaxScale) {

scale =mMaxScale / scale;

    }

//缩放

            mScaleMatrix.postScale(scaleFactor, scaleFactor, detector.getFocusX(), detector.getFocusY());

            checkBorderAndCenterWhenScale();

            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;

        RectF rectF = getMatrixRectF();

        switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:

if (rectF.width() > getWidth() +0.01 || rectF.height() > getHeight() +0.01) {

if (getParent()instanceof ViewPager)

getParent().requestDisallowInterceptTouchEvent(true);

                }

case MotionEvent.ACTION_MOVE:

if (rectF.width() > getWidth() +0.01 || rectF.height() > getHeight() +0.01) {

if (getParent()instanceof ViewPager)

getParent().requestDisallowInterceptTouchEvent(true);

                }

float dx = x -mLastX;

                float dy = y -mLastY;

                if (!isCanDrag) {

isCanDrag = isMoveAction(dx, dy);

                }

if (isCanDrag) {

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);

                        checkBorderAndTranslate();

                        setImageMatrix(mScaleMatrix);

                    }

}

mLastX = x;

                mLastY = y;

break;

            case MotionEvent.ACTION_UP:

case MotionEvent.ACTION_CANCEL:

mLastPointerCount =0;

break;

        }

return true;

    }

//当移动时进行边界检查

    private void checkBorderAndTranslate() {

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) >mTouchSlop;

    }

//获得图片放大缩小以后的宽和高 以及margin

    private RectF getMatrixRectF() {

Matrix matrix =mScaleMatrix;

        RectF rectF =new RectF();

        Drawable drawable = getDrawable();

        if (drawable !=null) {

rectF.set(0, 0, drawable.getIntrinsicWidth(), drawable.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 /2 - rect.right + rect.width() /2;

        }

if (rect.height() < height) {

deltaY = height /2 - rect.bottom + rect.height() /2;

        }

mScaleMatrix.postTranslate(deltaX, deltaY);

    }

}

activity代码


class ssactivity{

private ViewPagermViewPager;

private int[]mImgs = {R.mipmap.guoma, R.mipmap.xue, R.mipmap.xuezhiqian};

private ImageView[]mImageViews =new ImageView[mImgs.length];

@Override

protected void initView() {

mViewPager = (ViewPager) findViewById(R.id.id_viewPager);

    mViewPager.setAdapter(new PagerAdapter() {

@Override

        public ObjectinstantiateItem(ViewGroup container, int position) {

ZoomImageView zoomImageView =new ZoomImageView(getApplicationContext());

            zoomImageView.setImageResource(mImgs[position]);

            container.addView(zoomImageView);

            mImageViews[position] = zoomImageView;

            return zoomImageView;

        }

@Override

        public void destroyItem(ViewGroup container, int position, Object object) {

container.removeView(mImageViews[position]);

        }

@Override

        public int getCount() {

return mImageViews.length;

        }

@Override

        public boolean isViewFromObject(View view, Object object) {

return view == object;

        }

});

}

}

你可能感兴趣的:(viewPager中的多点触控图片)