控件树的触摸事件派发小结

当一个触摸事件产生后,它的传递过程遵循如下顺序:Activity→Window→View。

所以Activity的rootView收到一个触摸事件后,就会按照控件树的触摸事件派发流程,而事件的派发流程由ViewGroup(View)的dispatchTouchEvent(MotionEvent ev),其实dispatchTouchEvent方法在执行事件派发前,还控制确定派发目标的逻辑,在这里就略过确定派发目标的分析了,直接来分析事件派发:

这里只说单点触摸的情况而略过多点触摸的情况,那么多于单点触摸就只有一个完整的事件序列中,就只有一个子序列(多点触摸有多个子序列),那么事件序列的开始就是手指按下(触发ACTION_DOMN),结束就是手指抬起(触发ACTION_UP)。

派发目标:即在ACTION_DOWN事件,被确定为该事件序列的接受目标View。只有在ACTION_DOWN时,才回去寻找派发目标,在该序列接下来的事件中该目标View的父控件将事件直接传给该目标的dispatchTouchEvent方法。

1.只有消耗了Down的child才会成为ViewGroup的派发目标,即在child.dispatchTouchEvent方法中返回了true。

2.一个事件序列只有一个派发目标(再次强调只针对单点触摸)。

3.派发目标的dispatchTouchEvent方法即使返回了一个true,父控件及父控件的父控件都不会再进行处理的了。最后只有Activity的的onTouchEvent方法会处理这个没人处理的事件。

4.除非父控件被设置requestDisallowInterceptTouchEvent(true);即不可拦截事件标志,否则父控件可拦截经过它的任何事件,只要在onIntercept方法中返回true,即可设置ViewGroup的Intercepted变量为true,此时父控件下的作为其派发目标的child依然会受到此事件(是收到被拦截的事件,而不是之后的事件序列),该事件的action被改成了ACTION_CANCEL,该目标View收到action为ACTION_CANCEL的事件后,该序列接下来的事件它都接收不到,因为它已经从父控件的派发目标列表中移除了。该序列接下来的事件都由父控件处理了。

5.控件disallowIntercept标志可以干扰该控件对事件的截取,该标志被置为true时,该控件无法调用其onIntercept()方法进行对事件的拦截。但是在ACTION_DOWN事件时除外,就是说当该事件的action为ACTION_DOWN的时候,无论disallowIntercept是否为true,该控件都可以截取,只要DOWN事件经过该控件。ViewGroup截取了DOWN事件,则其child无论如何都没有机会去处理这些事件序列。

6.VIewGrou处理事件的时候,调用super.dispatchTouchEvent(即View#dispatchTouchEvent,这应该与ViewGroup#dispatchTouchEvent区分开),在View#dispatchTouchEvent方法中,处理流程是:若设置了OnToucListener,则调用OnTouchListener.onTouch(MotinoEvent ev)(每个控件只有一个OnTouchListener),若OnTouchListener.onTouch返回false,则调用View#onTouchEvent方法,在这方法中判断各种中View的属性,如clickable,longClickable,若clickable或longClickable为true,且设置onClickListener则或调用onClickListener.onClick(注意:此方法没有返回值,OnLongClickListener有返回值)。当clickable或longClickable为true,View#onTouchEvent一定返回true,否则返回若没有任何监听器则返回false。

7.OnClickListener和OnLongClickListener一起使用会有些细节需要注意,这里先不说下次再补上。

8.View的longClickable属性默认为false,clickable属性要分情况,比如Button的clickable默认为true,TextView的默认为false。

9.View的enable属性不影响onTouchEvent的默认返回值,哪怕一个View是disable状态,只要它的clickable或者longClickable有一个为true,则onTouchEvent就返回true。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值