移动开发中比较常见的手势操作有放大、缩小、旋转等。但是这其中大多数为两指实现的对图片操作手势。但是个别特殊情况例如对某个对话框进行手势操作,这样就需要用到单指实现操作手势了。相对于两指算法,单指要麻烦一些,特别对于数学不好的童鞋来说很难想到。因此特别写出来让大家参考一下。(虽然旋转的算法也是受了别人的启示才写出来,具体在哪里看到了忘记了)

不BB直接上代码:

public boolean onTouch(View v, MotionEvent event) {
            int DEFAULT_MOVE = 10;// 手指移动小于该值认为没有移动
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    parentX = event.getX();
                    parentY = event.getY();
                    mLastPoint.set(parentX, parentY);
                    oldDistance4PointF = distance4PointF(mCenterPoint, mLastPoint);
                    //在没有点击到view的情况下点击到了父布局
                    if (!isTouch) {
                        PublicViewHolder.getInstance().setTextFalse();
                    }
                    break;
                case MotionEvent.ACTION_MOVE:
                    float x = event.getX();
                    float y = event.getY();
                    if (!isTouch)
                        break;
                    mTouchPoint.set(x, y);
                    if (translateMode) {
                        /**
                         * 判断位移
                         */
                        int changeX = (int) (x - mLastPoint.x);
                        int changeY = (int) (y - mLastPoint.y);
                        translationX += changeX;
                        translationY += changeY;
                        setTranslationX(translationX);
                        setTranslationY(translationY);
                    } else {
                        /**
                         * 判断放大缩小
                         */
                        scale();
                        /**
                         * 判断旋转
                         */
                        rotation();
                    }
                    oldDistance4PointF = distance4PointF(mCenterPoint, mTouchPoint);
                    mLastPoint.set(x, y);
                    break;
                case MotionEvent.ACTION_UP:
                    /**
                     * 判断当位移值小于制定大小 触发编辑事件
                     */
                    if (Math.abs(event.getX() - parentX) < DEFAULT_MOVE && Math.abs(event.getY() - parentY) < DEFAULT_MOVE && isTouch && !isDeleteTouch) {
                        editListener.onEdit();
                    }
                    translateMode = true;
                    isTouch = false;
                    break;
            }
            return true;
        }

    /**
     * 两个点之间的距离
     *
     * @return
     */
    private float distance4PointF(PointF pf1, PointF pf2) {
        float disX = Math.abs(pf2.x - pf1.x);
        float disY = Math.abs(pf2.y - pf1.y);
        return (float) Math.sqrt(disX * disX + disY * disY);
    }

    private void scale() {
        float newDistance4PointF = distance4PointF(mCenterPoint, mTouchPoint);
        float vDistance = newDistance4PointF - oldDistance4PointF;
        if (vDistance > 0) {
            //放大
            scaleL(vDistance / oldDistance4PointF);
        } else if (vDistance < 0) {
            //缩小
            scaleM(-vDistance / oldDistance4PointF);
        }
    }
    public float scale = 1;
    private float reScale = 1;

    private void scaleL(float multiple) {
        scale += multiple;
        reScale -= multiple;
        setScaleX(scale);
        setScaleY(scale);
        scaleBar(reScale);
    }

    private void scaleM(float multiple) {
        scale -= multiple;
        reScale += multiple;
        if (scale <= 0.3) {
            scale = 0.3f;
            return;
        }
        setScaleX(scale);
        setScaleY(scale);
        scaleBar(reScale);
    }

    private void scaleBar(float scale) {
        if (scale <= 0.5)
            scale = 0.5f;
        if (scale >= 1.0)
            scale = 1.0f;
        touchBar.setScaleX(scale);
        touchBar.setScaleY(scale);
        deleteBar.setScaleX(scale);
        deleteBar.setScaleY(scale);
        editBar.setScaleX(scale);
        editBar.setScaleY(scale);
    }

    public float degrees = 0;
    //center -> proMove的向量, 我们使用PointF来实现
    PointF centerToProMove = new PointF();
    //center -> curMove 的向量
    PointF centerToCurMove = new PointF();

    private void rotation() {
        //旋转所组成三角形三边边长
        float a = oldDistance4PointF;
        float b = distance4PointF(mLastPoint, mTouchPoint);
        float c = distance4PointF(mCenterPoint, mTouchPoint);
        float cosArc = (a * a + c * c - b * b) / (2 * a * c);
        float newDegree = (float) Math.toDegrees(Math.acos(cosArc));
        centerToProMove.set((mLastPoint.x - mCenterPoint.x), (mLastPoint.y - mCenterPoint.y));
        centerToCurMove.set((mTouchPoint.x - mCenterPoint.x), (mTouchPoint.y - mCenterPoint.y));
        //向量叉乘结果, 如果结果为负数, 表示为逆时针, 结果为正数表示顺时针
        float result = centerToProMove.x * centerToCurMove.y - centerToProMove.y * centerToCurMove.x;
        if (result < 0) {
            newDegree = -newDegree;
        }
        if (Float.valueOf(newDegree).isNaN())
            return;
        degrees += newDegree;
        setRotation(degrees);

    }

放大、缩小比较简单大概提一下,由于写这个的时候是判断点击到了一个touchBar之后才能进行手势操作,所以为了避免touchbar缩小太多无法被点到,对放大缩小的设置了一个极值。