事件分发机制

  • Post author:
  • Post category:其他



目录


MotionEvent


三个方法


流程


事件分发的开始:


事件分发流程:



事件分发机制

指当屏幕上发生MotionEvent时,找到一个合适的view来处理消耗这个事件的过程。



MotionEvent

当用户触摸屏幕时会产生一个事件,将这个事件封装为MotionEvent,常见的MotionEvent有:


DOWN

:首次按下屏幕时触发


MOVE

:在屏幕上滑动时触发,可多次触发


UP

:离开屏幕时触发


CANCEL

:当事件中途被上层拦截时触发


三个方法

三个主要的方法来完成这个流程:

dispatchTouchEvent()

onIntercepterTouchEvent()

onTouchEvent()

方法

dispatchTouchEvent()

onIntercepterTouchEvent()

onTouchEvent()

作用

分发事件

拦截事件

处理消费事件

调用时刻

事件被传入view时

ViewGroup中的dispatchTouchEvent();

当一个事件将要被分发给子View时调用

dispatchTouchEvent()调用;

先调用onTouchListener判断是否消费,不消费才调用onTouchEvent()

存在位置

View, ViewGroup,Activity等

ViewGroup

View, ViewGroup(默认没有重写)

返回

true:分发成功

false:分发失败

true:将事件拦截

false:未拦截事件

true:处理事件

false:未处理事件

使用

可复写

若有需要去拦截事件,需要去复写该方法

复写该方法去消费事件


流程

触摸事件发生后会交给Android的输入系统服务InputManagerService(IMS),IMS会从 WMS中获取要发送的window,然后将事件发送给对应的viewRootImpl(viewRootImpl用来管理整个view树的绘制,事件分发等)。


事件分发的开始:

  • viewRootImpl接收到事件信息,封装成motionEvent对象后,发送给管理的view;
  • view会根据自身的类型,对事件进行分发还是自己处理,如果是一个view则处理,如果是一个viewGroup则根据viewGroup的类型进行分发;
  • activity和dialog等布局界面的顶层viewGroup一般是DecorView,DecorView在dispatchTouchEvent()会根据自身callBack的情况,选择调用callBack(activity、dialog实现了windowCallBack接口)或者调用父类ViewGroup的事件分发方法。

事件分发流程:


  • 一个触控点的事件序列只能给一个view消费


  • actionMasked == MotionEvent.ACTION_DOWN || mFirstTouchTarget != null

一旦拦截一个down事件或者没有子view消费事,后续对应的move、up等都不会再判断是否拦截。

  1. 一旦拦截一个事件交由自己的ontouchEvent处理,后续该事件也由此viewGroup处理;
  2. 某个View一旦开始处理事件,如果它不消耗ACTION_DOWN事件(onTouchEvent返回了false),那么同一件序列中的其他事件都不会再交给它处理,将重新交由它的父元素去处理。

  • 如果一个view消耗了DOWN事件却在接下来的MOVE或UP事件返回了false,那么此事件不会给上层的viewGroup处理,并且当前View可以持续收到后续的事件,最终这些消失的点击事件会传递给Activity处理。
  • 当viewGroup拦截子view的move或up事件之后,会将当前事件改为cancel事件并发送给子view。下一次的事件才会交由viewGroup消费。
  • 子view可以请求viewGroup不要拦截down之外的事件。通过requestDisallowInterupt方法强制要求viewGroup不要拦截事件,viewGroup中会设置一个

    FLAG_DISALLOW_INTERCEPT

    标志表示不拦截事件。但这只针对于down事件之外的事件,因为down事件会对该标志重置。
  • 如果外部注册了onTouchListener,onTouch优于onTouchEvent调用,如果返回true则表示消费了该事件,将不会调用onTouchEvent。
  • View的onTouchEvent默认都会消耗事件(返回true),除非它是不可点击的(clickable和longClickable同时为false)。View的longClickable属性默认为false,clickable属性要分情况,比如Button的clickable属性默认为true,而TextView的clickable属性默认为false。
  • onTouchEvent,处理ACTION_UP事件时,会触发performClick方法,如果这个view设置了onClickListenter就会调用onClick方法。



版权声明:本文为yu_ren_原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。