美文网首页
viewPager中的多点触控图片

viewPager中的多点触控图片

作者: SlideException | 来源:发表于2018-04-10 11:34 被阅读0次

    慕课网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()<mMidScale) {

    //                    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 <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, 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中的多点触控图片

          本文链接:https://www.haomeiwen.com/subject/puvghftx.html