Android手势事件相关

1.MotionEvent和TouchSlop

手指触碰屏幕会产生一些事件:
MotionEvent.ACTION_DOWN--手指刚触碰到屏幕
MotionEvent.ACTION_MOVE--手指在屏幕上移动
MotionEvent.ACTION_UP--手指从屏幕上离开的一瞬间

TouchSlop代表系统所能识别的最小滑动距离,如果小于这个距离就不认为是滑动操作
获取方式:

ViewConfiguration.get(getContext()).getScaledTouchSlop();

2.VelocityTracker

用于追踪手指在滑动过程中的速度,包括了水平速度和垂直速度。首先要在onTouchEvent方法中添加当前事件给速度追踪器:

VelocityTracker tracker = VelocityTracker.obtain();
tracker.addMovement(event);

然后需要设置速度单位,一般是像素/s、像素/500ms等,这个时间可以自己设置:

tracker.computeCurrentVelocity(500);

接着就可以得到水平、垂直两个方向上的速度:

int xVelocity = (int) tracker.getXVelocity();
int yVelocity = (int) tracker.getYVelocity();    

最后还有很重要的操作就是回收:

tracker.clear();
tracker.recycle();

3.GestureDetector

上面说到手势事件在MotionEvent中提供了三个基本的事件,如果我们想触发双击、拖动、长按等事件就要用到GestureDetector:

private GestureDetector detector = new GestureDetector(getContext(), new GestureDetector.OnGestureListener() {
        @Override
        public boolean onDown(MotionEvent e) {//触碰屏幕瞬间
            return false;
        }
        @Override
        public void onShowPress(MotionEvent e) {}//轻触屏幕且未松开或拖动

        @Override
        public boolean onSingleTapUp(MotionEvent e) {//触碰后松开
            return false;
        }
        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
            return false;//按下屏幕并拖动
        }
        @Override
        public void onLongPress(MotionEvent e) {}//长按

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            return false;//快速滑动且松开
        }
    });

然后在onTouchEvent方法中添加事件:

detector.onTouchEvent(event);

如果还需要监听双击:

detector.setOnDoubleTapListener(new GestureDetector.OnDoubleTapListener() {
            @Override
            public boolean onSingleTapConfirmed(MotionEvent e) {
                return false;//严格的单击行为,后面不可能再紧跟着另一个单击,即这不可能是双击中的一次单击
            }

            @Override
            public boolean onDoubleTap(MotionEvent e) {
                return false;//双击。和onSingleTapConfirmed不可能共存
            }

            @Override
            public boolean onDoubleTapEvent(MotionEvent e) {
                return false;
            }
        });

一般情况下我们不去实现GestureDetector的几个接口方法,除非特别需要监听双击、长按等特殊事件

4.View点击事件的分发机制

即当一个MotionEvent事件产生了之后,系统需要把这个事件传递给一个具体的View,
而这个传递的过程就是分发过程。这个过程由三个方法共同完成:

    public boolean dispatchTouchEvent(MotionEvent e)
    用来进行事件分发,如果事件可以传递给当前View,那么此方法一定会被调用,
    返回结果受当前View的onTouchEvent方法和下级View的dispatchTouchEvent方法
    影响,表示是否消耗当前事件

    public boolean onInterceptTouchEvent(MotionEvent e)
    在dispatchTouchEvent方法内部调用,用来判断是否拦截某个事件,如果当前View
    拦截了就在当前View中处理事件,否则传递给子View处理。注意此方法只在ViewGroup
    中有,因为只有他存在子View,而且它默认不拦截任何事件,都传给子View去处理

    public boolean onTouchEvent(MotionEvent e)
    在dispatchTouchEvent方法中调用,用来处理点击事件,返回结果表示是否消耗
    当前事件,如果不消耗那么当前View将无法接收下一个事件

    三者的关联:

@override
public boolean dispatchTouchEvent(MotionEvent e) {
    boolean consume = false;
    if (onInterceptTouchEvent(e)) {//是否拦截当前事件
        consume = onTouchEvent(e);//拦截当前事件并在当前View中处理
    } else {
        consume = childView.dispatchTouchEvent(e);//不拦截当前事件并传递给子View
    }
    return consume;//是否消耗当前事件,不消耗则无法接收下一个事件
}

另外再来说说OnTouchListener、OnClickListener和onTouchEvent方法的联系:
如果一个View对象设置了OnTouchListener,那么就会回调onTouch方法,如果onTouch方法返回false,则当前View的onTouchEvent方法会被调用,否则不会被调用,由此可见OnTouchListener的优先级高于onTouchEvent。如果当前View对象设置了OnClickListener且重写了onTouchEvent方法,当你点击当前View对象时是不会执行onClick方法中的代码的,而是执行onTouchEvent方法中的逻辑,这个时候想要执行onClick方法就需要在onTouchEvent方法中加一句performClick()来并发执行onClick方法,可见OnClickListener的优先级要低于onTouchEvent。所以三者的优先级关系是:OnTouchListener>onTouchEvent>OnClickListener

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

我们间的空白格

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

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

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

打赏作者

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

抵扣说明:

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

余额充值