通过多点触控实现图片的放大、缩小、旋转、位移效果。


    private float oldX1 = 0;    private float oldX2 = 0;    private float oldY1 = 0;    private float oldY2 = 0;    private float oldRotation= 0;    private boolean isDRAG = true;    private float downX = 0;    private float downY = 0;    @Override    public boolean onTouchEvent(MotionEvent event) {        int DEFAULT_MOVE = 10;// 手指移动小于该值认为没有移动        //必须要& MotionEvent.ACTION_MASK 才能触发        //ACTION_POINTER_DOWN        switch (event.getAction()& MotionEvent.ACTION_MASK) {            case MotionEvent.ACTION_DOWN:                if (listener!=null)                listener.onUse(true);                oldX1 = event.getX();                oldY1 = event.getY();                downX = event.getX();                downY = event.getY();                break;            case MotionEvent.ACTION_POINTER_DOWN:                oldRotation = rotation(event);                oldX1 = event.getX(0);                oldX2 = event.getX(1);                oldY1 = event.getY(0);                oldY2 = event.getY(1);                break;            case MotionEvent.ACTION_MOVE:                /**                 * 判断是否多点触控                 */                if (event.getPointerCount()>=2){                    /**                     * 判断是否点击后没有移动                     */                    isDRAG = false;                    float nowDifferentX = Math.abs(event.getX(0) - event.getX(1));                    float oldDifferentX = Math.abs(oldX1 - oldX2);                    float nowDifferentY = Math.abs(event.getY(0) - event.getY(1));                    float oldDifferentY = Math.abs(oldY1 - oldY2);                    //判断放大缩小                    if (nowDifferentX - oldDifferentX > 0 && nowDifferentY - oldDifferentY > 0) {                        /**                         * 放大                         */                        float multiples = 1 + MULTIPLES;                        matrix.postScale(multiples, multiples, convertCenterX(), convertCenterY());                    } else if (nowDifferentX - oldDifferentX < 0 && nowDifferentY - oldDifferentY < 0){                        /**                         * 缩小                         */                        float multiples = 1 - MULTIPLES;                        matrix.postScale(multiples, multiples,  convertCenterX(), convertCenterY());                    }                    /**                     * rotation当前旋转角度                     */                    //判断旋转                    float nowRotation = rotation(event);                    float rotation = nowRotation - oldRotation;                    matrix.postRotate(rotation,  convertCenterX(), convertCenterY());// 旋轉                    oldX1 = event.getX(0);                    oldX2 = event.getX(1);                    oldRotation += rotation;                }else if (isDRAG){                    /**                     * 单指移动                     * 添加标识isDRAG 防止当多点触控其中一只手指离开时 变成单点                     */                    matrix.postTranslate(event.getX() - oldX1, event.getY() - oldY1);                    oldX1 = event.getX();                    oldY1 = event.getY();                }                invalidate();                break;            case MotionEvent.ACTION_UP:                if (event.getPointerCount() == 1) {                    isDRAG = true;                    if (listener!=null)                        listener.onUse(false);                    /**                     * 判断是否点击后没有移动                     */                    if (Math.abs(event.getX() - downX) < DEFAULT_MOVE && Math.abs(event.getY() - downY) < DEFAULT_MOVE                            && needHead) {                        startToAlbum();                    }                }                break;        }        return true;    }

优化版:旋转和放大操作同时只能响应一个,旋转放大原点基于手指位置计算

@Override    public boolean onTouchEvent(MotionEvent event) {        int DEFAULT_MOVE = 5;// 手指移动小于该值认为没有移动        //必须要& MotionEvent.ACTION_MASK 才能触发        //ACTION_POINTER_DOWN        switch (event.getAction() & MotionEvent.ACTION_MASK) {            case MotionEvent.ACTION_DOWN:                if (listener != null)                    listener.onUse(true);                oldX1 = event.getX();                oldY1 = event.getY();                downX = event.getX();                downY = event.getY();                break;            case MotionEvent.ACTION_POINTER_DOWN:                isOne = true;                isScale = false;                isRotate = false;                isDRAG = false;                oldRotation = rotation(event);                oldX1 = event.getX(0);                oldX2 = event.getX(1);                oldY1 = event.getY(0);                oldY2 = event.getY(1);                float nowDifferentX = Math.abs(event.getX(0) - event.getX(1));                float nowDifferentY = Math.abs(event.getY(0) - event.getY(1));                mPx = nowDifferentX / 2 + Math.min(event.getX(0), event.getX(1));                mPy = nowDifferentY / 2 + Math.min(event.getY(0), event.getY(1));                break;            case MotionEvent.ACTION_MOVE:                /**                 * 判断是否多点触控                 */                if (event.getPointerCount() >= 2) {                    /**                     * 放大缩小                     * 旋转                     * 同时只能存在一种                     */                    if (isOne) {                        isScale = scale(event, false);                        isRotate = rotate(event, false);                        if (isScale || isRotate) {                            isOne = false;                        }                    }                    if (isScale && !isRotate) {                        scale(event, true);                    } else if (!isScale && isRotate) {                        rotate(event, true);                    } else if (isRotate) {                        scale(event, true);                    }                    oldX1 = event.getX(0);                    oldX2 = event.getX(1);                    oldY1 = event.getY(0);                    oldY2 = event.getY(1);                } else if (isDRAG) {                    /**                     * 单指移动                     * 添加标识isDRAG 防止当多点触控其中一只手指离开时 变成单点                     *///                    LogUtil.setLog("transX: " + (event.getX(0) - oldX1) + " transY: " + (event.getY(0) - oldY1) + " oldX:" + oldX1 + " oldY: " + oldY1 + " X: " + event.getX(0) + " Y: " + event.getY(0) + " count: " + event.getPointerCount());                    matrix.postTranslate(event.getX(0) - oldX1, event.getY(0) - oldY1);                    oldX1 = event.getX(0);                    oldY1 = event.getY(0);                }                invalidate();                break;            case MotionEvent.ACTION_UP:                if (event.getPointerCount() == 1) {                    if (listener != null)                        listener.onUse(false);                    /**                     * 判断是否点击后没有移动                     */                    if (Math.abs(event.getX() - downX) < DEFAULT_MOVE && Math.abs(event.getY() - downY) < DEFAULT_MOVE                            && needHead && isDRAG) {                        selectDialog.show();                    }                    isDRAG = true;                }                break;        }        return true;    }    /**     * @param isChange 是否需要改变视图     * @return 是否进行了放大缩小操作     */    private boolean scale(MotionEvent event, boolean isChange) {        /**         * 判断是否点击后没有移动         * 两点间距离         */        float nowDifferentX = Math.abs(event.getX(0) - event.getX(1));        float oldDifferentX = Math.abs(oldX1 - oldX2);        float nowDifferentY = Math.abs(event.getY(0) - event.getY(1));        float oldDifferentY = Math.abs(oldY1 - oldY2);        float changeX = nowDifferentX - oldDifferentX;        float changeY = nowDifferentY - oldDifferentY;        //判断放大缩小        float max = Math.max(Math.abs(changeX), Math.abs(changeY));        if (changeX > 0 && changeY > 0) {            /**             * 放大             */            if (isChange) {                float multiples = 1 + MULTIPLES * max;                matrix.postScale(multiples, multiples, mPx, mPy);            }            return true;        } else if (changeX < 0 && changeY < 0) {            /**             * 缩小             */            if (isChange) {                float multiples = 1 - MULTIPLES * max;                matrix.postScale(multiples, multiples, mPx, mPy);            }            return true;        }        return false;    }private boolean rotate(MotionEvent event, boolean isChange) {        /**         * rotation当前旋转角度         */        //判断旋转        float nowRotation = rotation(event);        float rotation = nowRotation - oldRotation;        if (Math.abs(rotation) >= 1) {            if (isChange) {                matrix.postRotate(rotation, mPx, mPy);// 旋轉                oldRotation += rotation;            }            return true;        } else return false;    }// 取旋转角度    private float rotation(MotionEvent event) {        double delta_x = (event.getX(0) - event.getX(1));        double delta_y = (event.getY(0) - event.getY(1));        double radians = Math.atan2(delta_y, delta_x);        return (float) Math.toDegrees(radians);    }

放大计算方法:

当判断多指触控时,记录下当前两指的坐标点,在MOVE事件触发后,计算当前两指之间的距离和两指位置改变之前的距离,并进行比较,若距离变大则为放大,若距离缩小则为缩小。


旋转计算方法:

// 取旋转角度    private float rotation(MotionEvent event) {        double delta_x = (event.getX(0) - event.getX(1));        double delta_y = (event.getY(0) - event.getY(1));        double radians = Math.atan2(delta_y, delta_x);        return (float) Math.toDegrees(radians);    }
通过以上方法获得当前两指形成的角度值,在判断多指触控时记录下初始角度,当触发move事件后重新计算角度值,其差值即为旋转了的角度。

更多相关文章

  1. Android圆形进度显示控件的SectorProgressView的使用
  2. Linux/Android(安卓)多点触摸支持
  3. 从android角度看2D加速图形引擎
  4. Android(安卓)源码系列之从源码的角度深入理解IntentService及Ha
  5. android 问题汇总系列之七
  6. Android(安卓)进阶学习:事件分发机制完全解析,带你从源码的角度彻
  7. 2011.10.12(2)——— android Matrix学习01
  8. Android(安卓)Activity跳转出现白屏但不闪退的现象
  9. 从源码角度理解HandlerThread和IntentService

随机推荐

  1. android write file
  2. Android(安卓)深入研究SQLite实例(二)
  3. android 使图片显示 圆角
  4. Android操作系统11种传感器介绍
  5. Android获取Manifest中元素的值
  6. android用intent打开各种文件
  7. 【转】Android(安卓)studio2.2.3 支持Jav
  8. [转]处理各种触摸事件
  9. 网页链接拉起Unity Android和iOS APP
  10. android 获取设备唯一标识:imei 通过Telep