手势识别器大全

http://blog.csdn.net/harvic880925/article/details/39520901 博客资料 
GestureDetector这个类对外提供了两个接口和一个外部类
接口:OnGestureListener,OnDoubleTapListener
内部类:SimpleOnGestureListener   和接口一样支持基本的单击和双击效果
内部类 :ScaleGestureListener   缩放的效果
OnDown(MotionEvent e):用户按下屏幕就会触发;
onShowPress(MotionEvent e):如果是按下的时间超过瞬间,而且在按下的时候没有松开或者是拖动的,那么onShowPress就会执行,具体这个瞬间是多久,我也不清楚呃……
onLongPress(MotionEvent e):长按触摸屏,超过一定时长,就会触发这个事件
    触发顺序:
    onDown->onShowPress->onLongPress
    onDown->onShowPress->onLongPress
    onDown->onShowPress->onLongPress
onSingleTapUp(MotionEvent e):从名子也可以看出,一次单独的轻击抬起操作,也就是轻击一下屏幕,立刻抬起来,才会有这个触发,当然,如果除了Down以外还有其它操作,那就不再算是Single操作了,所以也就不会触发这个事件
    触发顺序:
    点击一下非常快的(不滑动)Touchup:
    onDown->onSingleTapUp->onSingleTapConfirmed 
    点击一下稍微慢点的(不滑动)Touchup:
    onDown->onShowPress->onSingleTapUp->onSingleTapConfirmed
onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY) :滑屏,用户按下触摸屏、快速移动后松开,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE, 1个ACTION_UP触发   
     参数解释:
    e1:第1个ACTION_DOWN MotionEvent
    e2:最后一个ACTION_MOVE MotionEvent
    velocityX:X轴上的移动速度,像素/秒
    velocityY:Y轴上的移动速度,像素/秒   
    e1:第1个ACTION_DOWN MotionEvent
    e2:最后一个ACTION_MOVE MotionEvent
    velocityX:X轴上的移动速度,像素/秒
    velocityY:Y轴上的移动速度,像素/秒   
    e1:第1个ACTION_DOWN MotionEvent
    e2:最后一个ACTION_MOVE MotionEvent
    velocityX:X轴上的移动速度,像素/秒
    velocityY:Y轴上的移动速度,像素/秒   
onScroll(MotionEvent e1, MotionEvent e2,float distanceX, float distanceY):在屏幕上拖动事件。无论是用手拖动view,或者是以抛的动作滚动,都会多次触发,这个方法       在ACTION_MOVE动作发生时就会触发
    滑屏:手指触动屏幕后,稍微滑动后立即松开
    onDown-----》onScroll----》onScroll----》onScroll----》………----->onFling
    拖动
    onDown------》onScroll----》onScroll------》onFiling
    滑屏:手指触动屏幕后,稍微滑动后立即松开
    onDown-----》onScroll----》onScroll----》onScroll----》………----->onFling
    拖动
    onDown------》onScroll----》onScroll------》onFiling
    滑屏:手指触动屏幕后,稍微滑动后立即松开
    onDown-----》onScroll----》onScroll----》onScroll----》………----->onFling
    拖动
    onDown------》onScroll----》onScroll------》onFiling
    可见,无论是滑屏,还是拖动,影响的只是中间OnScroll触发的数量多少而已,最终都会触发onFling事件!

demo案列1 通过实现接口来实现接口:OnGestureListener,OnDoubleTapListener
package demo.com.myapplication;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity implements View.OnTouchListener {

    private GestureDetector mGestureDetector;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //1、创建OnGestureListener监听函数:
        GestureDetector.OnGestureListener listener = new gestureListener();
        //2、创建GestureDetector实例mGestureDetector:
        mGestureDetector = new GestureDetector(listener);
          //如果需要添加双击事件的监听可以写这个
        mGestureDetector.setOnDoubleTapListener(new doubleTapListener());
        //4、控件绑定
        TextView tv = (TextView) findViewById(R.id.tv);
        tv.setOnTouchListener(this);
        tv.setFocusable(true);//获取焦点
        tv.setClickable(true);//可点击
        tv.setLongClickable(true);//可长按的
    }

    //3、onTouch(View v, MotionEvent event)中拦截:
    /*
     * 在onTouch()方法中,我们调用GestureDetector的onTouchEvent()方法,将捕捉到的MotionEvent交给GestureDetector
     * 来分析是否有合适的callback函数来处理用户的手势
     */
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        return mGestureDetector.onTouchEvent(event);
    }

    private class gestureListener implements GestureDetector.OnGestureListener {
        // 用户轻触触摸屏,由1个MotionEvent ACTION_DOWN触发
        @Override
        public boolean onDown(MotionEvent e) {
            Log.i("MyGesture", "onDown");
            Toast.makeText(MainActivity.this, "onDown", Toast.LENGTH_SHORT).show();
            return false;
        }

        /*
         * 用户轻触触摸屏,尚未松开或拖动,由一个1个MotionEvent ACTION_DOWN触发
         * 注意和onDown()的区别,强调的是没有松开或者拖动的状态
         * 而onDown也是由一个MotionEventACTION_DOWN触发的,但是他没有任何限制,
         * 也就是说当用户点击的时候,首先MotionEventACTION_DOWN,onDown就会执行,
         * 如果在按下的瞬间没有松开或者是拖动的时候onShowPress就会执行,如果是按下的时间超过瞬间
         * (这块我也不太清楚瞬间的时间差是多少,一般情况下都会执行onShowPress),拖动了,就不执行onShowPress。
         */
        @Override
        public void onShowPress(MotionEvent e) {
            Log.i("MyGesture", "onShowPress");
            Toast.makeText(MainActivity.this, "onShowPress", Toast.LENGTH_SHORT).show();
        }
        // 用户(轻触触摸屏后)松开,由一个1个MotionEvent ACTION_UP触发
        ///轻击一下屏幕,立刻抬起来,才会有这个触发
        //从名子也可以看出,一次单独的轻击抬起操作,当然,如果除了Down以外还有其它操作,那就不再算是Single操作了,所以这个事件 就不再响应
        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            Log.i("MyGesture", "onSingleTapUp");
            Toast.makeText(MainActivity.this, "onSingleTapUp", Toast.LENGTH_SHORT).show();
            return true;
        }
        // 用户按下触摸屏,并拖动,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE触发
        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
            Log.i("MyGesture22", "onScroll:"+(e2.getX()-e1.getX()) +"   "+distanceX);
            Toast.makeText(MainActivity.this, "onScroll", Toast.LENGTH_LONG).show();

            return true;
        }
        // 用户长按触摸屏,由多个MotionEvent ACTION_DOWN触发
        @Override
        public void onLongPress(MotionEvent e) {
            Log.i("MyGesture", "onLongPress");
            Toast.makeText(MainActivity.this, "onLongPress", Toast.LENGTH_LONG).show();
        }
        // 用户按下触摸屏、快速移动后松开,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE, 1个ACTION_UP触发
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            Log.i("MyGesture", "onFling");
            Toast.makeText(MainActivity.this, "onFling", Toast.LENGTH_LONG).show();
            return true;
        }
    }
    //OnDoubleTapListener监听
    private class doubleTapListener implements GestureDetector.OnDoubleTapListener {
        public boolean onSingleTapConfirmed(MotionEvent e) {
            Log.i("doubleTapListener", "onSingleTapConfirmed");
            Toast.makeText(MainActivity.this, "onSingleTapConfirmed", Toast.LENGTH_LONG).show();
            return true;
        }

        public boolean onDoubleTap(MotionEvent e) {
            Log.i("doubleTapListener", "onDoubleTap");
            Toast.makeText(MainActivity.this, "onDoubleTap", Toast.LENGTH_LONG).show();
            return true;
        }

        public boolean onDoubleTapEvent(MotionEvent e) {
            Log.i("doubleTapListener", "onDoubleTapEvent");
            Toast.makeText(MainActivity.this, "onDoubleTapEvent", Toast.LENGTH_LONG).show();
            return true;
        }
    }
demo案列2 通过实现内部类内部类:SimpleOnGestureListener实现
package demo.com.myapplication;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity implements View.OnTouchListener {
    private GestureDetector mGestureDetector;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mGestureDetector = new GestureDetector(new simpleGestureListener());
        TextView tv = (TextView) findViewById(R.id.tv);
        tv.setOnTouchListener(this);
        tv.setFocusable(true);
        tv.setClickable(true);
        tv.setLongClickable(true);
    }

    public boolean onTouch(View v, MotionEvent event) {
        // TODO Auto-generated method stub
        return mGestureDetector.onTouchEvent(event);
    }

    private class simpleGestureListener extends GestureDetector.SimpleOnGestureListener {

        /*****
         * OnGestureListener的函数
         *****/
        public boolean onDown(MotionEvent e) {
            Log.i("MyGesture", "onDown");
            Toast.makeText(MainActivity.this, "onDown", Toast.LENGTH_SHORT).show();
            return false;
        }

        public void onShowPress(MotionEvent e) {
            Log.i("MyGesture", "onShowPress");
            Toast.makeText(MainActivity.this, "onShowPress", Toast.LENGTH_SHORT).show();
        }

        public boolean onSingleTapUp(MotionEvent e) {
            Log.i("MyGesture", "onSingleTapUp");
            Toast.makeText(MainActivity.this, "onSingleTapUp", Toast.LENGTH_SHORT).show();
            return true;
        }

        public boolean onScroll(MotionEvent e1, MotionEvent e2,
                                float distanceX, float distanceY) {
            Log.i("MyGesture", "onScroll:" + (e2.getX() - e1.getX()) + "   " + distanceX);
            Toast.makeText(MainActivity.this, "onScroll", Toast.LENGTH_LONG).show();

            return true;
        }

        public void onLongPress(MotionEvent e) {
            Log.i("MyGesture", "onLongPress");
            Toast.makeText(MainActivity.this, "onLongPress", Toast.LENGTH_LONG).show();
        }

        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            Log.i("MyGesture", "onFling");
            Toast.makeText(MainActivity.this, "onFling", Toast.LENGTH_LONG).show();
            return true;
        }

        /*****
         * OnDoubleTapListener的函数
         *****/
        public boolean onSingleTapConfirmed(MotionEvent e) {
            Log.i("MyGesture", "onSingleTapConfirmed");
            Toast.makeText(MainActivity.this, "onSingleTapConfirmed", Toast.LENGTH_LONG).show();
            return true;
        }

        public boolean onDoubleTap(MotionEvent e) {
            Log.i("MyGesture", "onDoubleTap");
            Toast.makeText(MainActivity.this, "onDoubleTap", Toast.LENGTH_LONG).show();
            return true;
        }

        public boolean onDoubleTapEvent(MotionEvent e) {
            Log.i("MyGesture", "onDoubleTapEvent");
            Toast.makeText(MainActivity.this, "onDoubleTapEvent", Toast.LENGTH_LONG).show();
            return true;
        }


    }
}
案例 1  scale缩放效果 缩放图片
package demo.com.myapplication;

import android.annotation.TargetApi;
import android.app.Activity;
import android.graphics.Matrix;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
import android.widget.ImageView;

import java.text.DecimalFormat;

@TargetApi(Build.VERSION_CODES.N)
public class FirstActivity extends Activity implements View.OnTouchListener {
    private ImageView iv;
    private GestureDetector mGestureDetector;//单击和双击事件手势识别器
    private ScaleGestureDetector mScaleGestureDetector;//缩放事件手势识别器
    private Matrix matrix = new Matrix();
    private DecimalFormat df = new DecimalFormat("0.00");//格式化float保留两位小数
    private float lastScale = 5;//记录上次的缩放比例,下次缩放时是在此基础上进行的
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        iv = new ImageView(this);
        iv.setImageResource(R.mipmap.ic_launcher);
        iv.setScaleType(ImageView.ScaleType.MATRIX);//用矩阵来绘制
        setContentView(iv);
        //创建最基本的识别器
        mGestureDetector = new GestureDetector(this, (GestureDetector.OnGestureListener) new MyGestureListener());
        //创建缩放的效果的手势识别器,关联第一个listner
        mScaleGestureDetector = new ScaleGestureDetector(this, new ScaleGestureDetector.SimpleOnScaleGestureListener() {
            @Override
            public boolean onScale(ScaleGestureDetector detector) {
                float scale = detector.getScaleFactor(); //缩放因子,两指靠拢时小于1
                float x = detector.getFocusX(),
                        y = detector.getFocusY();//中心点坐标
                Log.i("bqt", "缩放手势  onScale," + df.format(scale) + "-" + df.format(x) + "-" + df.format(y));
                matrix.setScale(lastScale * scale, lastScale * scale);
                iv.setImageMatrix(matrix);
                return super.onScale(detector);
            }
            @Override
            public boolean onScaleBegin(ScaleGestureDetector detector) {
                Log.i("bqt", "缩放手势  onScaleBegin," + df.format(detector.getScaleFactor()));//始终是1
                return super.onScaleBegin(detector);
            }
            @Override
            public void onScaleEnd(ScaleGestureDetector detector) {
                super.onScaleEnd(detector);
                lastScale *= detector.getScaleFactor();
                Log.i("bqt", "缩放手势  onScaleEnd," + df.format(detector.getScaleFactor()));
            }
        });

    }
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        mGestureDetector.onTouchEvent(event);
        mScaleGestureDetector.onTouchEvent(event);
        return super.onTouchEvent(event);
    }
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        return false;//设置OnTouchListener时,返回值要为false,或者在onTouch()中将MotionEvent事件传给GestureDetector,才能使手势识别器生效
    }
    class MyGestureListener extends GestureDetector.SimpleOnGestureListener {
        @Override
        //双击的【第二下】Touch down时触发(只执行一次)
        public boolean onDoubleTap(MotionEvent e) {
            Log.i("bqt", "onDoubleTap");
            return super.onDoubleTap(e);
        }
        @Override
        //双击的【第二下】Touch down和up都会触发(执行次数不确定)。
        public boolean onDoubleTapEvent(MotionEvent e) {
            Log.i("bqt", "onDoubleTapEvent");
            return super.onDoubleTapEvent(e);
        }
        @Override
        //Touch down时触发
        public boolean onDown(MotionEvent e) {
            Log.i("bqt", "onDown");
            return super.onDown(e);
        }
        @Override
        //onScroll一点距离后,【抛掷时】触发(若是轻轻的、慢慢的停止活动,而非抛掷,则很可能不触发)
        //参数为手指接触屏幕、离开屏幕一瞬间的动作事件,及手指水平、垂直方向移动的速度,像素/秒
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            Log.i("bqt", "onFling");
            if ((e2.getRawX() - e1.getRawX()) > 100) {
                Log.i("bqt", "onFling-从左到右滑");
                return true;//消耗事件
            }
            return super.onFling(e1, e2, velocityX, velocityY);
        }
        @Override
        //Touch了不移动一直Touch down时触发
        public void onLongPress(MotionEvent e) {
            Log.i("bqt", "onLongPress");
            super.onLongPress(e);
        }
        @Override
        //Touch了滑动时触发,e1代表触摸时的事件,是不变的,e2代表滑动过程中的事件,是时刻变化的
        //distance是当前event2与上次回调时的event2之间的距离,代表上次回调之后到这次回调之前移动的距离
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
            Log.i("bqt", "onScroll-" + (int) e1.getX() + "-" + (int) e2.getX() + "-" + (int) distanceX + "-" + (int) distanceY);
            return super.onScroll(e1, e2, distanceX, distanceY);
        }
        @Override
        //Touch了还没有滑动时触发
        public void onShowPress(MotionEvent e) {
            Log.i("bqt", "onShowPress");
            super.onShowPress(e);
        }
        @Override
        //在touch down后又没有滑动(onScroll),又没有长按(onLongPress),然后Touchup时触发。
        public boolean onSingleTapConfirmed(MotionEvent e) {
            Log.i("bqt", "onSingleTapConfirmed");
            return super.onSingleTapConfirmed(e);
        }
        @Override
        //在touch down后又没有滑动(onScroll),又没有长按(onLongPress),然后Touchup时触发。
        public boolean onSingleTapUp(MotionEvent e) {
            Log.i("bqt", "onSingleTapUp");
            return super.onSingleTapUp(e);
        }
    }
}
案列 2 和上面一样缩放图片只不过不用收拾识别器而是利用view的特性
package demo.com.myapplication;

import android.app.Activity;
import android.graphics.Matrix;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;

public class SecondActivity extends Activity implements View.OnTouchListener {
    private ImageView iv;
    private float scale = 1;
    private float lastScale = 1;//记录手指全部离开时的缩放比例,下次缩放时是在此基础上进行的
    private float oldDist;//记录第二个触摸点和第一个触摸点之间的距离
    private Matrix mMatrix = new Matrix();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        iv = new ImageView(this);
        iv.setImageResource(R.mipmap.ic_launcher);
        iv.setBackgroundColor(0x8822ffff);//从背景可以看出,此ImageView 是占用整个屏幕大小的
        iv.setScaleType(ImageView.ScaleType.MATRIX);
        iv.setOnTouchListener(this);
        setContentView(iv);
    }
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getActionMasked()) {
            case MotionEvent.ACTION_DOWN:
                Log.i("bqt", "ACTION_DOWN,第一个触摸点,所以肯定为【1】" + event.getPointerCount());
                break;
            case MotionEvent.ACTION_UP://当屏幕上唯一的点被放开时触发
                lastScale = scale;//记录手指全部离开时的缩放比例,下次缩放时是在此基础上进行的
                Log.i("bqt", "ACTION_UP,最后一个触摸点,之前触摸点数肯定为【1】" + event.getPointerCount());
                break;
            case MotionEvent.ACTION_POINTER_UP://当屏幕上有多个点被按住,松开其中一个点时触发
                Log.i("bqt", "ACTION_POINTER_UP,少一个触摸点,少之前的触摸点数为" + event.getPointerCount());
                break;
            case MotionEvent.ACTION_POINTER_DOWN://当屏幕上已经有一个点被按住,此时再按下其他点时触发
                if (event.getPointerCount() == 2)
                    oldDist = spacing(event);//记录第二个触摸点和第一个触摸点之间的距离
                Log.i("bqt", "ACTION_POINTER_DOWN,又一个触摸点,目前触摸点数为" + event.getPointerCount());
                break;
            case MotionEvent.ACTION_MOVE://当有点在屏幕上移动时触发
                if (event.getPointerCount() == 2) {
                    float newDist = spacing(event);//移动过程中,第二个点和第一个点的距离
                    if (Math.abs(newDist - oldDist) > 10) {//减小灵敏度
                        scale = lastScale * newDist / oldDist;
                        Log.i("bqt", "ACTION_MOVE,缩放比例为" + scale);
                        mMatrix.setScale(scale, scale);
                        iv.setImageMatrix(mMatrix);
                    }
                }
                break;
        }
        return true;
    }
    /**
     * 返回两个点之间的距离
     */
    private float spacing(MotionEvent event) {
        if (event.getPointerCount() >= 2) {
            float x = event.getX(0) - event.getX(1);
            float y = event.getY(0) - event.getY(1);
            return (float) Math.sqrt(x * x + y * y);
        } else return 0;
    }
}
案列 3 //MotionEvent示例:功能增强 和上面两个的区别在于这个还额外的可以单只手移动图片
package demo.com.myapplication;


import android.app.Activity;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;


public class ThirdActivity extends Activity implements View.OnTouchListener {
    private ImageView imageView;
    private Matrix startMatrix = new Matrix();//ImageView初始矩阵
    private Matrix matrix = new Matrix();//要给ImageView设置的矩阵
    private float startDis;//两个手指的按下时的初始距离
    private PointF midPoint;//两个手指的按下时中间点
    private PointF startPoint = new PointF();//第一个手指按下时的坐标位置
    private boolean isPointerUp;//当有手指放开时,如果不停止缩放,会导致图片位置错乱。后续可以优化
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        imageView = new ImageView(this);
        imageView.setImageResource(R.mipmap.ic_launcher);
        imageView.setOnTouchListener(this);
        imageView.setScaleType(ImageView.ScaleType.MATRIX);
        setContentView(imageView);
    }
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getActionMasked()) {
            case MotionEvent.ACTION_DOWN:
                Log.i("bqt", "初始矩阵" + imageView.getImageMatrix());//值是会变的 {[1.0, 0.0, 0.0][0.0, 1.0, 0.0][0.0, 0.0, 1.0]}
                startMatrix.set(imageView.getImageMatrix());//获取初始状态
                startPoint.set(event.getX(), event.getY());//获取开始时候的坐标位置
                isPointerUp = true;
                break;
            case MotionEvent.ACTION_MOVE:
                if (isPointerUp) {
                    if (event.getPointerCount() == 1) { //移动图片
                        float dx = event.getX() - startPoint.x; // 得到X轴的移动距离
                        float dy = event.getY() - startPoint.y; // 得到Y轴的移动距离
                        Log.i("bqt", "移动距离" + (int) dx + "---" + (int) dy);
                        matrix.set(startMatrix);//先置为初始状态
                        matrix.postTranslate(dx, dy);
                    } else if (event.getPointerCount() == 2) { // 放大缩小图片
                        float endDis = distance(event);// 距离
                        float scale = endDis / startDis;//ImageView缩放的比例
                        Log.i("bqt", "缩放倍数" + scale);
                        matrix.set(startMatrix);
                        matrix.postScale(scale, scale, midPoint.x, midPoint.y);
                    }
                    imageView.setImageMatrix(matrix);
                }
                break;
            case MotionEvent.ACTION_POINTER_DOWN:
                startDis = distance(event);
                midPoint = mid(event);
                startMatrix.set(imageView.getImageMatrix());//重置为目前的初始状态
                break;
            case MotionEvent.ACTION_UP:
                break;
            case MotionEvent.ACTION_POINTER_UP:
                isPointerUp = false;
                break;
        }
        return true;
    }
    /** 计算两个手指间的距离 */
    private float distance(MotionEvent event) {
        float dx = event.getX(1) - event.getX(0);
        float dy = event.getY(1) - event.getY(0);
        /** 使用勾股定理返回两点之间的距离 */
        return (float) Math.sqrt(dx * dx + dy * dy);
    }
    /** 计算两个手指间的中间点 */
    private PointF mid(MotionEvent event) {
        float midX = (event.getX(1) + event.getX(0)) / 2;
        float midY = (event.getY(1) + event.getY(0)) / 2;
        return new PointF(midX, midY);
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BACKWASH2038

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值