GestureDetector —— 手势检测

GestureDetector —— 手势检测

在Android开发中我们可能需要监听用户的手势:单击、双击、长按、滑动、缩放等,而在View的onTouchEvent只能单纯地对DOWN、MOVE和UP事件作处理,往往需要做出很多判断才能达到想要的效果。所以GestureDetector为我们封装了以上事件的监听。

概述

GestureDetector类提供了两个接口和一个内部类:OnGestureListener,OnDoubleTapListenerSimpleOnGestureListener

GestureDetector常用的三个构造函数:

GestureDetector gestureDetector = new GestureDetector(GestureDetector.OnGestureListener listener);
GestureDetector gestureDetector = new GestureDetector(Context context,GestureDetector.OnGestureListener listener);
GestureDetector gestureDetector = new GestureDetector(Context context,GestureDetector.SimpleOnGestureListener listener);

使用步骤

1⃣️ 声明GestureDetector

    private GestureDetector mGestureDetector;

2⃣️ 初始化GestureDetector

mGestureDetector = new GestureDetector(this, new GestureDetector.XxxListener() {
     //Override方法...
 });

3⃣️ 为目标View设置onTouchListener,将GestureDetector的onTouchEvent事件返回

 txtShow.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                return mGestureDetector.onTouchEvent(event);
            }
        });

接口中函数的说明

GestureDetector.OnGestureListener

该接口提供六个函数:
  1. onDown(MotionEvent e):按下触发。
  2. onShowPress(MotionEvent e):按下超过一会,并且无松开或拖动就会触发。
  3. onSingleTapUp(MotionEvent e):轻击抬起屏幕就会触发。
  4. onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY):在屏幕上拖动就会触发。⚠️e1:第1个ACTION_DOWN,e2:最后一个ACTION_MOVE
  5. onLongPress(MotionEvent e):长按屏幕触发。
  6. onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY):快速滑动会触发。⚠️参数12同4

GestureDetector.OnDoubleTapListener

⚠️ 注意实现OnDoubleTapListener前必须实现OnGestureListener接口。因为初始化GestureDetector时,构造函数不支持OnDoubleTapListener的传入。
只有两种方法设置OnDoubleTapListener,1⃣️ 创建类同时实现两个接口 ,2⃣️ 调用GestureDetector的setOnDoubleTapListener()方法。

该接口提供三个构造函数
  1. onSingleTapConfirmed(MotionEvent e):单击事件。
  2. onDoubleTap(MotionEvent e):双击事件。
  3. onDoubleTapEvent(MotionEvent e):双击间隔中的事件。

GestureDetector.SimpleOnGestureListener类

该类实现了上面两个接口的实现,通过继承该类可以选择需要监听的函数。

举个例子?

下面通过该例子研究事件的触发顺序。

1⃣️ 首先在XML中添加TextView
2⃣️ 在Activity中按照设置GestureDetector顺序为其添加监听


public class GestureActivity extends BaseActivity {

    private TextView txtShow;
    private GestureDetector mGestureDetector;
    private static final String TAG = "GestureActivity-zz";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_gesture);
        initView();
        setListener();
    }

    private void initView() {
        Toolbar toolbar = findViewById(R.id.include).findViewById(R.id.toolbar);
        NavigationView nav = findViewById(R.id.nav_view);
        DrawerLayout dawer = findViewById(R.id.drawer_layout);
        initToolbar(toolbar, nav, dawer);
        txtShow = findViewById(R.id.gesture_txt_demo);
    }

    @SuppressLint("ClickableViewAccessibility")
    private void setListener() {
        txtShow.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                return mGestureDetector.onTouchEvent(event);
            }
        });

        mGestureDetector = new GestureDetector(this, new GestureDetector.OnGestureListener() {
            @Override
            public boolean onDown(MotionEvent e) {
                txtShow.setText("OnDown");
                Log.i(TAG, "onDown: ");
                return true;
            }

            @Override
            public void onShowPress(MotionEvent e) {
                txtShow.setText("onShowPress");
                Log.i(TAG, "onShowPress: ");
            }

            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                txtShow.setText("onSingleTapUp");
                Log.i(TAG, "onSingleTapUp: ");
                return true;
            }

            @Override
            public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
                txtShow.setText("onScroll," + "x的距离:" + distanceX + ",y的距离:" + distanceY);
                Log.i(TAG, "onScroll: ");
                return true;
            }

            @Override
            public void onLongPress(MotionEvent e) {
                txtShow.setText("onLongPress");
                Log.i(TAG, "onLongPress: ");
            }

            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                txtShow.setText("onFling," + "x的速度:" + velocityX + ",y的速度" + velocityY);
                Log.i(TAG, "onFling: ");
                return true;
            }
        });

        // 设置双击接口
        mGestureDetector.setOnDoubleTapListener(new GestureDetector.OnDoubleTapListener() {
            @Override
            public boolean onSingleTapConfirmed(MotionEvent e) {
                txtShow.setText("onSingleTapConfirmed");
                Log.i(TAG, "onSingleTapConfirmed: ");
                return true;
            }

            @Override
            public boolean onDoubleTap(MotionEvent e) {
                txtShow.setText("onDoubleTap");
                Log.i(TAG, "onDoubleTap: ");
                return true;
            }

            @Override
            public boolean onDoubleTapEvent(MotionEvent e) {
                txtShow.setText("onDoubleTapEvent");
                Log.i(TAG, "onDoubleTapEvent: ");
                return true;
            }
        });
    }
}

3⃣️ 效果如下:
gesture1.gif

事件的触发顺序

⚠️事件的触发顺序:

  1. 长按:onDown -> onShowPress -> onLongPress
  2. 快速点击:onDown -> onSingleTapUp -> onSingleTapConfirmed
  3. 稍微慢点的点击: onDown -> onShowPress -> onSingleTapUp -> onSingleTapConfirmed
  4. 手指触动屏幕后,稍微滑动后立即松开:onDown -> onScroll -> onScroll ->………–> onFling
  5. 拖动: onDown -> onScroll -> onScroll -> onFiling
  6. 双击:onDown -> onSingleTapUp -> onDoubleTap -> onDoubleTapEvent -> onDown -> onDoubleTapEvent

其他注意事项

在子线程中使用GestureDetector

1⃣️ 首先该子线程必须有Looper,则如下创建

new Thread(new Runnable() {
    @Override public void run() {
        Looper.prepare(); 
        final GestureDetector detector = new GestureDetector(MainActivity.this, new
                GestureDetector.SimpleOnGestureListener());
        //...
    }
}).start();

2⃣️ 使用主线程的Looper创建handler传入构造函数

new Thread(new Runnable() {
    @Override public void run() {
        final Handler handler = new Handler(Looper.getMainLooper());
        final GestureDetector detector = new GestureDetector(MainActivity.this, new
                GestureDetector.SimpleOnGestureListener() , handler);
        // ...
    }
}).start();

ScaleGestureDecetor —— 缩放手势检测

概述

1.构造函数

ScaleGestureDetector(Context context, ScaleGestureDetector.OnScaleGestureListener listener)

ScaleGestureDetector(Context context, ScaleGestureDetector.OnScaleGestureListener listener, Handler handler)

2.外部接口和类

interface OnScaleGestureListener
public static class SimpleOnScaleGestureListener implements OnScaleGestureListener

3.3个方法

boolean onScale(ScaleGestureDetector detector) // 缩放被触发。如果返回true表示缩放事件被处理
boolean onScaleBegin(ScaleGestureDetector detector) // 缩放开始,两个手指在屏幕上就会被调用
void onScaleEnd(ScaleGestureDetector detector)  // 缩放结束

应用同GestureDetector

        imgView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                return scaleGestureDetector.onTouchEvent(event);
            }
        });

        scaleGestureDetector = new ScaleGestureDetector(this, new ScaleGestureDetector.OnScaleGestureListener() {
            @Override
            public boolean onScale(ScaleGestureDetector detector) {
                txtShow.setText("focusX = " + detector.getFocusX() + "\n" + "focusY = " + detector.getFocusY()
                        + "\n" + "scale = " + detector.getScaleFactor());
                return true;
            }

            @Override
            public boolean onScaleBegin(ScaleGestureDetector detector) {
                return true;
            }

            @Override
            public void onScaleEnd(ScaleGestureDetector detector) {

            }
        });

原理和图片缩放例子参考

图片缩放例子涉及MATRIX

安卓自定义View进阶-缩放手势检测(ScaleGestureDecetor)

参考文章

  1. 用户手势检测-GestureDetector使用详解
  2. 安卓自定义View进阶-手势检测(GestureDetector)
  3. 官方文档
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值