美文网首页Android自定义ViewAndroid缩放
android双指缩放和双指拖拽控件

android双指缩放和双指拖拽控件

作者: andy_db22 | 来源:发表于2020-12-02 20:10 被阅读0次

    author:andy

    问题:产品要求,做成双指缩放且双指拖拽

    android市面上应用最常见的一个功能是双指缩放,然后单指拖拽。比如最著名的PhotoView开源,就是典型代表。然而Google了半天基本找不到双指缩放和双指拖拽的完整资料,而且网上也有一些用户提出相同的问题,然而并没有好的开源,就自己整了个。

    先上图:


    gif.gif

    思路流程图:


    双指缩放和拖拽.jpg

    注意的事项:
    MotionEvent:对应的几个关键事件
    MotionEvent.ACTION_POINTER_DOWN: 第二根以上手指触摸屏幕触发:
    在第二个手指的监听记录初始位置,记录2个手指开始的间距oldDist:

     case MotionEvent.ACTION_POINTER_DOWN:
                    if (pointerCount == 2) {
                        downX1 = event.getX(0);
                        downX2 = event.getX(1);
                        downY1 = event.getY(0);
                        downY2 = event.getY(1);
                        Log.d(TAG, "ACTION_POINTER_DOWN 双指按下 downX1=" + downX1 + " downX2="
                                + downX2 + "  downY1=" + downY1 + " downY2=" + downY2);
                        oldDist = spacing(event); //两点按下时的距离
                    }
    

    手指移动过程缩放和移动处理:
    oldDist:2手指初始距离
    moveDist: 2手指移动后的距离
    space: 2手指变化距离
    缩放比例:float scale = (float) (getScaleX() + space / v.getWidth());

    移动处理:以2指中心点变化值作为移动范围

    case MotionEvent.ACTION_MOVE:
                   if (pointerCount == 2) {
                       float x1 = event.getX(0);
                       float x2 = event.getX(1);
                       float y1 = event.getY(0);
                       float y2 = event.getY(1);
    
                       double changeX1 = x1 - downX1;
                       double changeX2 = x2 - downX2;
                       double changeY1 = y1 - downY1;
                       double changeY2 = y2 - downY2;
    
                       if (getScaleX() > 1) { //滑动
                           float lessX = (float) ((changeX1) / 2 + (changeX2) / 2);
                           float lessY = (float) ((changeY1) / 2 + (changeY2) / 2);
                           setSelfPivot(-lessX, -lessY);
                           Log.d(TAG, "此时为滑动");
                       }
                       //缩放处理
                       moveDist = spacing(event);
                       double space = moveDist - oldDist;
                       float scale = (float) (getScaleX() + space / v.getWidth());
                       if (scale < SCALE_MIN) {
                           setScale(SCALE_MIN);
                       } else if (scale > SCALE_MAX) {
                           setScale(SCALE_MAX);
                       } else {
                           setScale(scale);
                       }
                   }
                   break;
    

    间距计算

        /**
         * 计算两个点的距离
         *
         * @param event
         * @return
         */
        private double spacing(MotionEvent event) {
            if (event.getPointerCount() == 2) {
                float x = event.getX(0) - event.getX(1);
                float y = event.getY(0) - event.getY(1);
                return Math.sqrt(x * x + y * y);
            } else {
                return 0;
            }
        }
    

    平移

        /**
         * 平移画面,当画面的宽或高大于屏幕宽高时,调用此方法进行平移
         *
         * @param x
         * @param y
         */
        public void setPivot(float x, float y) {
            setPivotX(x);
            setPivotY(y);
        }v
    

    平移加上屏幕边界处理

        /**
         * 移动
         *
         * @param lessX
         * @param lessY
         */
        private void setSelfPivot(float lessX, float lessY) {
            float setPivotX = 0;
            float setPivotY = 0;
            setPivotX = getPivotX() + lessX;
            setPivotY = getPivotY() + lessY;
            if (setPivotX < 0 && setPivotY < 0) {
                setPivotX = 0;
                setPivotY = 0;
            } else if (setPivotX > 0 && setPivotY < 0) {
                setPivotY = 0;
                if (setPivotX > getWidth()) {
                    setPivotX = getWidth();
                }
            } else if (setPivotX < 0 && setPivotY > 0) {
                setPivotX = 0;
                if (setPivotY > getHeight()) {
                    setPivotY = getHeight();
                }
            } else {
                if (setPivotX > getWidth()) {
                    setPivotX = getWidth();
                }
                if (setPivotY > getHeight()) {
                    setPivotY = getHeight();
                }
            }
            setPivot(setPivotX, setPivotY);
        }
    

    碰到的问题:

    最初构思的时候,走进了个误区,以为缩放和拖拽必须二选一,于是出现很多的计算判断用户到底是缩放还是拖拽,然后相应处理,然而无论怎么计算,发现都有瑕疵(体现在:滑动时候出现缩放,缩放时有时候又夹杂滑动,导致感觉不流畅),最后发现其实根本无需如此,二者完全可以共存,而且体验完全流畅.

    最后上代码: https://github.com/androidsihai1/ScaleDemo

    相关文章

      网友评论

        本文标题:android双指缩放和双指拖拽控件

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