您的位置:首页 > 移动开发 > Android开发

Android开发中的事件分发和消费机制的一些理解

2017-11-10 16:28 323 查看
说明
事件分发被用作解决事件冲突,还被用作自定义View
事件包含的动作

1.ACTION_DOWN(按下):手指只要一触摸屏幕就立即触发这个动作

2.ACTION_MOVE(移动):手指触摸屏幕,并在屏幕上移动一段距离。

3.ACTION_UP(抬起):手指离开屏幕的一瞬间就立即触发该动作。
三个动作,伴随三个方法

事件分发(dispatchTouchEvent),事件拦截(onInterceptTouchEvent),事件消费(onTouchEvent)

事件分发:将事件分发给拦截方法或者消费方法来处理。

事件拦截:该方法将事件拦截下来。不会直接传给下一级元素。

事件消费:最终这个事件被消费掉了。
Android提供可了三个控件来调用者三个事件方法的

                                                Activity                    ViewGroup                      View(终极控件)

dispatchTouchEvent                 true                             true                                    true

onInterceptTouchEvent            false                            true                                    false

onTouchEvent                          true                              true                                   true

1.activity为什么没有拦截方法?

            如果Activity有拦截,那么它将可以是一个没有界面的Service,那么将跟Service冲突。
2.View为什么没有拦截方法?

           因为View属于终结控件,View没有子控件,也不能添加子控件,拦截没有意义。dispatchTouchEvent:它是一个分发方法,它拿到这个事件之后,只能调用onIntercepteTouchEvent或者onTouchEvent来传递这个事件,一般不去考虑这个返回值onIntercepteTouchEvent:它是一个拦截方法,它拿到dispatchTouchEvent传来的事件之后,判断自身是否要拦截,如果拦截该事件【也就是该方法的返回值为true】,那么它将直接调用当前控件自身的onTouchEvent来处理。如果不拦截该事件【采用默认的返回值或者返回值设置为false】,那么它将直接调用子控件的dispatchTouchEvent来分发。onTouchEvnet:它是一个消费方法,默认值是不消费的。不消费那么它将直接将该事件交于父控件或者组件来处理。
一个单击或者移动的动作的事件处理过程

1.单击    按下是谁消费了,抬起就一定得让谁消费。前后是同一个对象

2.移动    按下是前提,按下谁消费,抬起就谁消费。前后是同一个对象

总结:按下是谁消费,移动和抬起的动作就是谁来消费。
单击事件分发响应验证



单机 = 按下 + 抬起

A:Activity                      VG:ViewGroup                         V:View
1.采用默认值的方式,在界面中执行单机,方法调用过程是?

          A:dispatch -> VG:dispatch -> VG:onIntercept -> V:dispatch -> V:onTouch -> VG:onTouch -> A:onTouch【按下事件消费结束】-> A:dispatch -> A:onTouch【抬起事件消费结束,单机事件完成】
2.让ViewG
4000
roup拦截该事件,也就是拦截方法返回true,其他方法默认。

          A:dispatch -> VG:dispatch -> VG:onIntercept -> VG:onTouch -> A:onTouch【按下动作消费结束】-> A:dispatch -> A:onTouch【抬起事件消费结束,单机事件完成】
3.让View消费该事件,也就是view的onTouchEvent返回true,其他方法默认。

          A:dispatch -> VG:dispatch -> VG:onIntercep -> V:dispatch -> V:onTouch【按下动作消费结束】-> A:dispatch -> VG:dispatch -> VG:onIntercept -> V:dispatch ->V:onTouch【抬起事件消费结束,单机事件完成】
4.让ViewGroup消费该事件,就是ViewGroup的onTouchEvent返回true,其他方法默认

          A:dispatch -> VG:dispatch -> VG:onIntercept -> V:dispatch -> V:onTouch -> VG:onTouch【按下事件消费结束】-> A:dispatch -> VG:dispatch -> VG:onTouch【抬起事件消费结束,单机事件完成】
给控件设置长按监听或者单击监听事件
1.只要给控件激活Clickable属性或者LongClickable属性,那么控件就可以消费按下动作。

         1.直接在布局中给定这个clickable属性或者longclickable这个属性,并将它设置为true

         2.可以直接给控件设置对应的监听方法。(OnClickListener,OnLongClickListener)
2.给View设置单击监听事件,其他方法返回值默认

         A:dispatch -> VG:dispatch -> VG:onIntercept -> V:dispatch -> V:onTouch【激活了Cliable属性】【按下事件消费结束】-> A:dispatch -> VG:dispatch ->VG:onIntercept -> V:dispatch -> V:onTouch【抬起事件消费结束】-> V:onClick【单机事件结束】
3.给View设置长按监听事件,其他方法返回值默认

         A:dispatch -> VG:dispatch -> VG:onIntercept -> V:dispatch -> V:onTouch【激活了Cliable属性】【按下事件消费结束】【->OnLongClick(必须要达到长按的时间标准,方可执行)】-> A:dispatch -> VG:dispatch -> VG:onIntercept -> V:dispatch -> V:onTouch【抬起事件消费结束】
4.给View设置单击事件和长按事件监听,方法的返回值默认

         1.LongClick这个方法的返回值为false,默认值

                    A:dispatch -> VG:dispatch -> VG:onIntercept -> V:dispatch -> V:onTouch【激活了Cliable属性】【按下事件消费结束】【->OnLongClick(必须要达到长按的时间标准,方可执行)】-> A:dispatch -> VG:dispatch -> VG:onIntercept -> V:dispatch -> V:onTouch【抬起事件消费结束】-> V:onClick【单机事件结束】      
                           

         2.LongClick这个方法的返回值设置为true

                    onClick方法和onLongClick方法有且只有一个方法被执行,另外一个方法不执行。

         结论:给控件设置单击和长按监听,会激活控件的Clickable属性和onLongClick属性,只要激活这任意一个属性,那么该控件就会消费该事件,就不会想上层传了。
【补充】

       dispatchTouchEvent 方法,在这个方法内,首先是进行了一个判断,里面有三个条件,如果这三个条件都满足,就返 回true,否则就返回onTouchEvent方法执行的结果。对于第一个条件是一个mOnTouchListener变量,这个变量是在View中的setOnTouchListener方法里赋值的,也就是说只要我们给控件注册了touch事件,mOnTouchListener就一定被赋值了。第二个条件是判 断当前点击的控件是否是enable的,按钮默认都是enable的,因此这个条件恒定为true。第三个条件最为关键,
mOnTouchListener.onTouch(this, event),其实也就是去回调控件注册touch事件时的onTouch方法。也就是说如果我们在onTouch方法里返回true,就会让这三个条件全部成立,从而整个方法直接返回true。如果我们在onTouch方法里返回false,就会再去执行onTouchEvent(event)方法。结合我之前讲的例子,首先在 dispatchTouchEvent中最先执行的就是onTouch方法,因此onTouch肯定是要优先于onClick执行的,而如果在onTouch方法里返回了true,就会让
dispatchTouchEvent 方法直接返回true,不会再继续往下执行。

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: