Android触摸事件传递机制学习笔记

1、Android 触摸事件传递机制
http://blog.csdn.net/awangyunke/article/details/22047987
2、Android-onInterceptTouchEvent()和onTouchEvent()总结
http://blog.csdn.net/lvxiangan/article/details/9309927
3、Android onTouchEvent, onClick及onLongClick的调用机制
http://blog.csdn.net/ddna/article/details/5451722
4、Android: 详解触摸事件如何传递
http://www.cnblogs.com/superlcr/p/3946034.html?utm_source=tuicool
一、涉及的类和方法
Activity,View,ViewGroup(View的子类)
1)public boolean dispatchTouchEvent(MotionEvent ev) 这个方法用来分发TouchEvent,在Activity和View里分别定义
这个方法尝试将触摸事件交给自己的子视图 (如果有的话) 处理: 调用子视图的 dispatchTouchEvent()
或者自己处理: 调用自己的 onTouchEvent() 或 OnTouchListener.onTouch()(优先调用)
无论是自己的子视图,还是自己,只要完成了事件处理,都返回 true
2)public boolean onInterceptTouchEvent(MotionEvent ev) 这个方法用来拦截TouchEvent
ViewGroup单独定义的方法,如果事件需要在该 ViewGroup 截断 (自己处理该事件, 不再传递给其子视图), 则返回 true
3)public boolean onTouchEvent(MotionEvent ev) 这个方法用来处理TouchEvent 在Activity和View里分别定义
这个方法尝试自己处理触摸事件. 如果完成处理 (不需要再交给其他 View 处理), 则返回 true
二,传递流程
从Activity的dispatchTouchEvent开始,这是触摸事件的入口,没有重写的情况下会无条件的传递给根视图ViewGroup的dispatchTouchEvent,经过如下图的流程,返回true表示ViewGroup消费了事件,返回false则返回Activity自己的 onTouchEvent() 方法。

这里写图片描述

如果ViewGroup 还有子视图,且仍然没有截断的话,会继续调用子视图的子视图,如此递归进行。触摸事件派遣的顺序是自上而下的。直到到达某个叶子 View (不再有子视图可以派遣),或者某个 ViewGroup 虽然还有子视图可以派遣,但其截断 onInterceptTouchEvent() 方法返回 true。这时,触摸事件真正开始尝试进行处理。

处理方法:如果注册了触摸事件监听器 OnTouchLisener,则优先调用 OnTouchLisener.onTouch() 方法,如果没有注册监听器,或OnTouchLisener.onTouch() 方法返回 false,再尝试调用 ViewGroup 自身的 onTouchEvent() 方法

如果该 View 完成了触摸事件的处理 (返回 true),那么对于其父视图而言,dispatchTouchEvent() 方法派遣给子视图的事件圆满完成,可以向自己的父视图宣称完成事件了 (返回 true)。反之,如果该 View 自己没有完成触摸事件,对于其父视图 ViewGroup 而言,派遣子视图并没有完成事件处理,只好自己处理。如果再次没有完成,父视图会向自己的父视图返回 false,如果各层 ViewGroup 均不能完成事件处理,最终会调用 Activity 的 onTouchEvent() 方法,做最后的尝试。整个实际处理过程顺序正好相反,是自下而上的。

三、onClick、onLongClick和onTouchEvent
在 onTouchEvent() 中,会判断触摸是否构成一次点击事件,从而交给其他一些监听器,如 onClickListener (监听点击事件),onLongClickListener (监听长按事件) 来处理,同时返回 true。

onTouchEvent()方法的判断:

case MotionEvent.ACTION_DOWN:
    mPrivateFlags |= PRESSED;
    refreshDrawableState();
    if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
         postCheckForLongClick(); //发起CheckForLongPress线程的执行,条件都满足后会设置OnLongClickListener
    }
    break;

case MotionEvent.ACTION_UP:
    if ((mPrivateFlags & PRESSED) != 0) {
         boolean focusTaken = false;
         if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
               focusTaken = requestFocus();
         }
    if (!mHasPerformedLongPress) {
       if (mPendingCheckForLongPress != null) {
             removeCallbacks(mPendingCheckForLongPress);
       }

       if (!focusTaken) {
              performClick();//设置OnClickListener
       }
    }
    …
    break;

长按事件顺序:onTouch ACTION_DOWN——onLongClick——onTouch ACTION_UP
点击事件顺序:onTouch ACTION_DOWN——onTouch ACTION_UP——onClick

onLongClick的发生是在ACTION_UP之前,而onClick的发生是在ACTION_UP后,如果在onLongClick()方法的最后return true,则不会再触发onClick;如果return false的话会在ACTION_UP后仍然触发onClick。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值