触摸事件分发机制总结

从手指触摸到设备屏幕,直至手指离开设备屏幕,这个过程会不断的产生触摸事件,Framework称之为MotionEvent

分发机制这是用于解决View的嵌套、重叠所产生的触摸事件应该由哪个view来响应的问题;比如:


点击上图中的button,这个点击的事件到底是应该由button响应呢,还是framelayout来响应呢。分发机制就是解决这样的问题的。负责事件分发的方法是dispatchTouchEvent(MotionEvent ev)

分发的过程是:

1.分发事件的起点是触摸事件所在的Activity 调用其dispatchTouchEvent();

2.然后是此ActivityrootView.dispatchTouchEvent();

3.前序遍历rootViewView树,依次调用其ViewGroup(View)dispatchTouchEvent()



dispatchTouchEvent(MotionEvent ev),所有的View都通过这个方法实现事件的分发,ViewGroupView的子类,对这个方法进行了覆盖;

ViewdispatchTouchEvent的机制是:

1.该方法将返回一个boolean值,默认返回false;其返回true,意味着当前View将消费触摸事件;比如,在ActivitydispatchTouchEvent返回了true,则事件就被分发到Activity,其rootViewrootView下的ViewGroupView均被屏蔽;

2.dispatchTouchEvent方法内部的逻辑是:

(1)检查当前的View是否注册了onTouchListener

(2)若注册了onTouchListener,则执行onTouchListner.onTouch()方法

(3)若onTouchListner.onTouch()返回了true,表示当前View消费了此次触摸事件,dispatchTouchEvent将返回true

(4)若未注册onTouchListener,或注册了onTouchListener.onTouch()方法返回了false,则执行onTouchEvent();

(5)我们熟知的onClickListener.onClick()等方法均在onTouchEvent()方法中调用,只要执行了onTouchEvent()方法,则dispatchTouchEvent一定会返回true

ViewGroupdispatchTouchEvent的机制是:

1.ViewdispatchTouchEvent所均有的特性ViewGroupdispatchTouchEvent也具有;

2.其逻辑是:

(1)判断ViewGroup是否拦截此次触摸消息,即disallowIntercept||!onInterceptTouchEvent();这个地方就需要插播一下了。

A.分发机制的总体思想是,从层次结构上来说,自上向下的分发,而最底层的View具有最高的优先级去处理触摸事件(因为dispatchTouchEvent默认返回false),只有最底层的View未对触摸事件进行处理(dispatchTouchEvent也返回false),更高层次的ViewGroup才有机会处理触摸事件。

B.这里onInterceptTouchEvent()方法的意思是,拦截触摸事件,它是对上述机制的一个补充,它为高层次的ViewGroup提供了一个屏蔽底层View的方法,只有ViewGroup不拦截触摸事件,其子View才有机会去分发和处理;

C.disallowIntercept这个参数的作用是,否决掉ViewGroup的拦截,这种设计可以使事件的处理更为灵活。这个disallowIntercept参数可以由requestDisallowInterceptTouchEvent()方法来修改。这里需要注意的是,disallowIntercept否决作用的生命周期只是一次触摸事件,如果想要在一系列的戳事件中,都屏蔽掉ViewGorup的拦截,则必须在每次触摸事件分发处理时都要修改disallowIntercept的值;

(2)若ViewGroup拦截了事件,则调用super.dispatchTouchEvent();

(3)若ViewGroup没有拦截事件,则遍历ViewGroup树,在每个ViewGroupView中调用dispatchTouchEvent

 

以上是分发机制的基本内容了,除此之外还有几个问题需要思考:

1.当dispatchTouchEvent在进行事件分发的时候,只有前一个action返回true,才会触发后一个action,我看到有人对这个结论表示不能理解。其实是这样的,比如一个点击动作,至少由两个触摸事件组成:ACTOIN_DOWN,ACTION_UP,前者是按下,后者是提起,考虑ACTION_DOWN被分发到最底层的控件view上,如果对于ACTON_DOWN这个事件,view.dispatchTouchEvent的返回值为false,则说明view对于这个事件“不感兴趣”,那么等到分发ACTION_UP事件时,view的父控件就会认为,既然ACTION_DOWNview忽略掉,那么ACIONT_UP对于view来说也是没有意义,如果根本不会将ACTION_UP分发给view了。

2.为什么要有onTouchonTouchEvent()两个方法呢?因为两个方法都是对触摸事件进行处理啊。我觉得可以从这两个方法的加载这个方面来理解,如果要在onTouch()中处理触摸事件,我们需要定义一个onTouchListener,并覆写其onTouch()方法,而onTouchEvent()方法是继承自View类的。如果需要改变控件对于触摸事件处理的特性,onTouch()onTouchEvent()方法都是可以做到的,区别在于:(1)onTouch()方法是通过接口形式实现的,onTouchEvent()是通过继承实现的;(2)onTouchEvent()是控件的固有属性,这个固有属性可以使得开发人员很方面的使用onClickListener这些框架内的触摸事件处理方式,通时,框架也提供了onTouch()方法,可用于屏蔽掉onTouchEvent()这个控件的固有属性;


总结一下,关于分发机制,最重要的几条:

(1)分发顺序Activity-->rootView->View树遍历

(2)dispatchTouchEvent返回true表示分发给自己,返回false表示“不感兴趣”

(3)dispatchTouchEvent内部先调用onTouch(),再调用onTouchEvent()

(4)ViewGroup通过onInterceptEvent()方法控制拦截,外部可通过disallowIntercept屏蔽ViewGroup的onInterceptEvent()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值