事件分发机制(一):解惑篇

前言

本文粗略解析下事件分发机制,后续会分析下源码,但愿可以帮助到你们解惑一二。函数

从一个例子提及cdn

在实践中,大多数须要了解事件分发机制的可能就是滑动冲突了,须要了解何时到底谁应该处理这个事件,先来看个例子,当咱们点击区域Viewblog

默认不处理事件

假如ViewGroup和View都默认不处理事件,不复写对应函数事件

  • DOWN事件传递到View的onTouchEvent,返回false,表示View自己不关心此次事件
  • DOWN事件传递到ViewGroup的onTouchEvent,返回false,表示ViewGroup自己不关心此次事件
  • 最终事件回溯到Activity中,由最上层处理事件

因为onTouchEvent中返回了false,同时也就表明着不关心本次事件(我不关心此次手势,不要来找我了),后续的MOVE,UP事件也不会传递进来源码

View处理事件

假设View是须要处理事件,好比是Button之类的View,默认是可点击的it

  • DOWN事件传递到View的onTouchEvent,返回True,处理本身的逻辑
  • 由于View中的onTouchEvent返回了True,表示有人愿意处理了这个事件,那么后续事件将不会传递到ViewGroup以及上层的onTouchEvent中了,后续的事件将由View自己进行处理

注意上述的前提是ViewGroup不会对此事件进行拦截,由于在DOWN事件传递到View的ontouchEvent以前,ViewGroup是有一次拦截机会的,若是ViewGroup的onInterceptTouchEvent返回false,则不拦截,可是注意下一次的MOVE、UP等事件仍是会走ViewGroup拦截的判断,可根据逻辑进行拦截处理,若是没有拦截,可是View的ontouchEvent返回了false,也就表示下面没有View是愿意处理这个事件的,那么这个烫手的山芋(事件)仍是会回到ViewGroup的ontouchEvent中io

同时可见DOWN事件的返回值,其实就是表示着View自己对本次事件处理的意愿如何,True则表明着愿意处理该事件,false则表明不关心本次事件class

ViewGroup拦截事件

假如ViewGroup在DOWN事件中,拦截了事件onInterceptTouchEvent返回了true,那么此时事件直接转到ViewGroup的ontouchEvent中,后续的MOVE、UP事件也会交给ViewGroup处理,View是没有机会处理到事件的,即便此时调用requestDisallowInterceptTouchEvent也是无效的request

假如ViewGroup在DOWN事件中没有拦截事件,可是在MOVE中却对事件进行了拦截处理,好比相似如ScrollView同样,是能够对其中的View进行点击处理的,可是在滑动时,ScrollView须要处理本身的逻辑,这时候就在MOVE中拦截了事件lazyload

  • DOWN事件传递在ViewGroup中,但此时并不想拦截,onInterceptTouchEvent返回false,事件传递到View的ontouchEvent中,消费掉返回True
  • MOVE事件传递到ViewGroup中,此时ViewGroup须要对事件进行拦截处理,onInterceptTouchEvent返回True,可是View还苦巴巴的等着事件呢,由于以前在ontouchEvent中返回了True,那么此时这个MOVE事件将会被系统变成一个CANCEL事件,这个CANCEL事件将会传递给VIEW的onTouchEvent方法,告诉你,别等了,你的事件被取消了
  • 当MOVE事件或者UP事件再次进入ViewGroup的时候,注意此时因为以前已经拦截了事件,这次事件并不会走onInterceptTouchEvent的判断,能够理解为onInterceptTouchEvent一旦返回了True,那么后续的一系列事件就默认已经被拦截处理了,不会再去判断!而是会直接传递给ViewGroup的onTouchEvent方法去处理了
  • 此时View就不会受到任何的事件了

总结

  • 同一时间序列事件是指以down事件开始,中间含有数量不定的move事件,最终以up事件结束。

  • 各个View的onTouchEvent方法对DOWN事件的处理,表明了该View对以此DOWN开始的整个手势事件的处理意愿,True表明须要处理这次事件,false则表示不关心,事件会回传到上层View的ontouchEvent中

  • 若是ViewGroup一旦决定拦截一个事件,也就是onInterceptTouchEvent返回True,那么后续的同一时间序列事件将会被默认拦截,不会再调用onInterceptTouchEvent方法,后续事件会交给ontouchEvent进行处理

  • 事件一旦交给一个View处理,那么它就必须消耗掉,不然同一事件序列中剩下的事件就再也不交给他来处理了,若是ontouchEvent中返回false,那么后续事件不会再传递进来

  • 若是ViewGroup拦截了一个半路的事件(好比,MOVE),这个事件将会被系统变成一个CANCEL事件,并传递给以前处理该手势(gesture)的子View,并且不会再传递(不管是被拦截的MOVE仍是系统生成的CANCEL)给ViewGroup的onTouchEvent方法。只有再到来的事件才会传递到ViewGroup的onTouchEvent方法中。

请帮顶 / 评论点赞!由于你的鼓励是我写做的最大动力!

相关文章
相关标签/搜索