Android 手势学习 GestureDetector

最近总感觉学过的知识总是忘了;还是应了那句老话,好记性不如烂笔头,所以,还是老老实实记录文字吧;

今天把手势 GestureDetector 记录一下;

一、简介

我们知道,当我们要处理一下复杂的手势时,如果还使用 onTouchListener ,那么则需要自己额外的去写一些判断逻辑;当然,google 已经为我们封装好了手势的实现类 GestureDetector ,只需要实现它的 Listener ,即可拿到自己想要的方法。
GestureDetector 提供了三个接口和一个内部类:

  • 接口 OnGestureListener
  • 接口 OnDoubleTapListener
  • 接口 OnContextClickListener
  • 内部类 SimpleOnGestureListener
    其中 OnContextClickListener 很容易联想到 context 的点击,但其实不是,是指外接设备,比如蓝牙笔按下时触发,在 API 23 后加入的,如果侦听 onContextClick(MotionEvent),则必须在 View 的 onGenericMotionEvent(MotionEvent)中调用 GestureDetector 的 OnGenericMotionEvent(MotionEvent)。一般也没怎么用到,所以这里不做解释,

二、手势介绍

手势介绍这里,我们就简单介绍一下OnGestureListener 和 OnDoubleTapListener 即可。

2.1 OnGestureListener

OnGestureListener 为GestureDetector 的一个方法,它的实现方法如下:

    class GestureListenerDemo implements GestureDetector.OnGestureListener{

        @Override
        public boolean onDown(MotionEvent e) {
            /**
             * 按下屏幕就会出发,需要返回true来消费这个事件,通过GestureDetector 源码就知道,
             * 返回true后,mDetector.onTouchEvent(event) 也会返回突然, 这样 onTouchEvent 的事件才不会继续传递
             */
            Log.d(TAG, "zsr onDown: ");
            return false;
        }

        @Override
        public void onShowPress(MotionEvent e) {
            /**
             * 当按下超过180ms时,就会触发,一般我们用这个来实现点击背景之类的
             */
            Log.d(TAG, "zsr onShowPress: ");
        }

        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            /**
             * 相当于 up 事件
             */
            Log.d(TAG, "zsr onSingleTapUp: ");
            return false;
        }

        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
            /**
             * 监听屏幕滑动,其中 e2 第二个触摸事件,distanceX 和 distanceY
             * 则为滑动距离
             */
            Log.d(TAG, "zsr onScroll: ");
            return false;
        }

        @Override
        public void onLongPress(MotionEvent e) {
            /**
             * 当手指按住屏幕不放,
             */
            Log.d(TAG, "zsr onLongPress: ");
        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            /**
             * 当手指快速滑动屏幕,则会触发 velocityX,velocityY 表示每秒滑动的距离(像素)
             */
            Log.d(TAG, "zsr onFling: ");
            return false;
        }
    }

GestureDetector 使用如下:

// 1、 拿到 GestureDetector 实例
mDetector = new GestureDetector(new GestureListenerDemo());
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // 2、在 onTouchEvent 中,调用 GestureDetector 的onTouchEvent
        return mDetector.onTouchEvent(event);

    }

上面的注释已经很清楚了,需要注意的是 onDown 需要返回 true,否则 onscroll 等方法不会调用,这里是因为要onTouchEvent 消费这些事件,具体可以看看事件分发机制。

2.2 OnDoubleTapListener

OnDoubleTapListener 为双击时调用的接口,它的实现也比较简单,首先继承该接口:

class DoubleListenerDemo implements GestureDetector.OnDoubleTapListener{

   @Override
   public boolean onSingleTapConfirmed(MotionEvent e) {
       /**
        * 点击事件,不像onSingleTapUp,当双击时 onSingleTapConfirmed 不会被调用
        */
       Log.d(TAG, "zsr onSingleTapConfirmed: ");
       return false;
   }

   @Override
   public boolean onDoubleTap(MotionEvent e) {
       /**
        * 双击,当第二下点击,down 事件触发
        */
       Log.d(TAG, "zsr onDoubleTap: ");
       return false;
   }

   @Override
   public boolean onDoubleTapEvent(MotionEvent e) {
       /**
        * 双击时触发,且 MotionEvent 会继续触发,可以监听 up 事件,
        * 在up事件处理逻辑
        */
       Log.d(TAG, "zsr onDoubleTapEvent: "+e.getAction());
       return false;
   }
}

然后需要在 GestureDetector 这里把监听事件添加进去:

mDetector = new GestureDetector(new GestureListenerDemo());
mDetector.setOnDoubleTapListener(new DoubleListenerDemo());

这里有几个接口要解释一下:
onSingleTapConfirmed() 和 onSingleTapUp 的区别在于,onSingleTapConfirmed 在双击事件时并不会被调用,而 onSingleTapUp 则是会继续调用,所以一些细微的逻辑处理可以从这里下手;
onDoubleTap 和 onDoubleTapEvent 的区别在于onDoubleTap 是第二次点击的 down事件时,就会触发,而 onDoubleTapEvent 方法中的 MotionEvent 都会被触发,所以也可以在这里做一些逻辑。

2.3 SimpleOnGestureListener

从上面看,还是有些奇怪的,我们除了要设置 OnGestureListener,如果监听双击,还得通过 setOnDoubleTapListener 把OnDoubleTapListener设置一下;其实 google 也考虑到了,所以才有了 SimpleOnGestureListener 这个内部类;
该类实现了 OnGestureListener,setOnDoubleTapListener 和 OnContextClickListener 的方法,只是里面都是空的,需要自己去实现。且不需要的可以不用重写,所以这个也是用的最多的。
如下,我们只需要双击事件:

    class  SimpleDemo extends GestureDetector.SimpleOnGestureListener{
        @Override
        public boolean onDown(MotionEvent e) {
            return true;
        }
        @Override
        public boolean onDoubleTap(MotionEvent e) {
            Log.d(TAG, "zsr 双击666");
            return false;
        }


    }

调用两个参数的构造函数即可:

mDetector = new GestureDetector(context,new SimpleDemo());

三、实例

经过上面的学习,接着我们学习一下,左滑退出,右滑进入其他 activity 的实例,可以很快想到用 onFlat 方法:

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            //实现左滑和右滑
            float distanceX = e2.getX() - e1.getX();
            if (distanceX > 100 && velocityX > 200){
                Log.d(TAG, "zsr onFling: 左滑退出");
            }
            if (distanceX < -100 && velocityX < -200){
                Log.d(TAG, "zsr onFling: 右滑进入其他activity");
            }
          //  Log.d(TAG, "onFling:迅速滑动,并松开");
            return false;
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值