view时间传递机制

来源:互联网 发布:淘宝卖家报复的买家 编辑:程序博客网 时间:2024/06/10 21:19

主要方法

  • publish boolean dispatcherTouchEvent(MotionEvent ev):如果事件能够传递给该view,该方法一定会调用,返回结果受当前view的onTouchEvent和下级view的dispatcherTouchEvent的影响,表示是否消耗当前事件。
  • publish boolean onInteceptTouchEvent(MotionEvent ev):用来判断是否拦截某个事件,如果当前view拦截了某个事件,那么在同一个事件序列中,此方法不会被再次调用,返回结果表示是否拦截当前事件
  • publish boolean onTouchEvent(MotionEvent ev):表示是否消耗当前事件,如果不消耗,则在同一事件序列中,当前view无法再次接收到事件
规则如下图所示


规律


1. 同一事件序列:从手指触摸屏幕那一刻起,到手指离开屏幕的那一刻结束,在这个过程中所产生的一系列事件,这个时间序列以down事件开始,中间包含了数量不定的move时间,最终以up事件结束。
2. 正常情况下,时间只能被一个View拦截且消耗,因为一旦一个元素拦截了某事件,那么同一事件序列内的事件都会直接交给它处理,因此同一事件序列中的事件不能由两个view同时处理,但是可以通过onTouchEvent强行传递给其他View处理。
3. 某个View一旦决定拦截事件,那么整个事件序列都会传递给该View,并且该View的onInterceptTouchEvent不会再调用。
4. 某个View开始处理事件,如果该View不消耗该事件(onToucheVent返回false),那么同一事件序列中的其他事件都不再由该View处理,并且事件将交由该View的父元素处理(调用父元素的onToucheVent)。
5. 如果View不消耗除ACTION_DOWN以外的其他事件,那么该点击事件会消失(不会调用父元素的onToucheVent),该View可以持续收到后续的事件序列,最终这些消失的事件序列会传递给Activity处理。
6. ViewGroup默认不拦截任何事件。
7. View没有onInterceptTouchEvent方法,一旦有事件传递过来就调用onToucheEvent(除非它是不可点击的)
8. View的enable属性不影响onToucheVent的默认返回值。如果一个view是disable状态的,只要它的clickable或者longClickable有一个为true,那么它的onToucheEvent就会返回true。
9. onClick发生的前提是View是可点击的并且收到了down和up事件
10. 事件分发由高向低。通过requestDisallowInterceptTouchEvent方法可以在子元素中干预父元素的事件分发过程,但是ACTION_DOWN除外(ACTION_DOWN 会重置标志位)
11. 某个View拦截事件并处理事件,同时该View设置了onTouchListener,则onTouch会调用,屏蔽了onTouchEvent,这样的好处是:方便在外界处理点击事件。

12.view的onToucheEvent默认都会消耗事件(返回true),除非它是不可点击的(clickable或者longClickable同时为false)。view的longClickable属性默认都是false,clickable属性要分情况,比如Button的clickable属性默认是true,而TextView的clickable属性默认是false。
13. View的事件的调度顺序是 onTouchListener > onTouchEvent > onLongClickListener > onClickListener 。

  • 单击事件(onClickListener) 需要两个两个事件(ACTION_DOWN 和 ACTION_UP )才能触发,如果先分配给onClick判断,等它判断完,用户手指已经离开屏幕,黄花菜都凉了,定然造成 View 无法响应其他事件,应该最后调用。(最后)
  • 长按事件(onLongClickListener) 同理,也是需要长时间等待才能出结果,肯定不能排到前面,但因为不需要ACTION_UP,应该排在 onClick 前面。(onLongClickListener > onClickListener)
  • 触摸事件(onTouchListener) 如果用户注册了触摸事件,说明用户要自己处理触摸事件了,这个应该排在最前面。(最前)
  • View自身处理(onTouchEvent) 提供了一种默认的处理方式,如果用户已经处理好了,也就不需要了,所以应该排在 onTouchListener 后面。(onTouchListener > onTouchEvent)
父元素在遍历子View的过程中,判断是否接收点击事件的标准是:
  1. 子元素是否在播放动画
  2. 点击事件的坐标是否落在子元素的区域内