事件分发机制
- 为什么会有事件分发机制
- 三个重要的事件分发的方法
- 事件分发流程
1.为什么会有事件分发机制
- android上的View是以属性结构绘制,所以说View的控件有可能重叠 在一起,所以当我们点击一块地方的时候,重叠的View可以同时相应,这时系统把点击事件判给谁呢?为了解决这个问题,就有了事件分发机制
图1、图2
PhoneWindow
Decorview
RootView
ViewGroupA view2
view1
- android上的View是以属性结构绘制,所以说View的控件有可能重叠 在一起,所以当我们点击一块地方的时候,重叠的View可以同时相应,这时系统把点击事件判给谁呢?为了解决这个问题,就有了事件分发机制
- 屏幕上没有View遮挡的部分,就会显示主题的颜色,而不仅如此,最上面的标题也没有出现在layout布局当中,这个标题显示在哪呢?主题 颜色和标题栏就是显示在DecorView当中
- Phonewindow 是抽象类Window的实现类
Window是所有视图的最顶级容器,包括了背景的显示,标题栏,事件的处理都是在Window管理范畴里。这个View对顶层的管理容器。真正的唯一实现类Phonewindow,
DecorView是Phonewindow的内部类。
- Phonewindow 是抽象类Window的实现类
2.三个重要的事件分发的方法
事件传递,事件分发到底是啥?
- dispatchTouchEvent
- onInterceptTouchEvent
- onTouchEvent
- Activity和View是没有第二个拦截事件的
1.Activity拦截事件会导致整个屏幕无法响应事件,这不是我们想要的用户体验的效果
2.View为事件传递的最末端,要么消费事件,要么不处理,没必要进行事件事件拦截,他的下面已经没有可以分发事件的子控件了
2.1 dispatchTouchEvent 最重要
- 决定了触摸事件是由自己的onTouchEvent处理还是分发给子View,让子View 递归的调用自身的dispatchTouchEvent来处理dispatchTouchEvent 和onInterceptTouchEvent的关系
前者会调用后者来判断是否进行拦截事件
2.2 onInterceptTouchEvent,拦截事件
- 当父控件下发事件给子控件进行处理的时候,如果子控件需要对事件进行处理,他就会在onIntercepTouchEvent这个里进行拦截,然后到子控件的onTouchEvent里面做触摸事件的监听和一些逻辑的判断
2.3 onTouchEvent
- View当中的一个方法,按下,移动,放开,取消
3.事件分发流程
Activity->PhoneWindow->DecorvView->ViewGroup->...->View
如果最后一个View没有消费事件,这个事件会反转到Activity最后被抛弃,责任链模式,上层的View 既可以拦截事件进行事件的处理,也可以下发询问子View是不是处理,如果是最底层了也没处理,就会返回到Activity
实例:图
4.事件的处理
1.外部拦截发:父容器重写onInterceptTouchEvent
- ACTION_DOWN
返回false不拦截。必须,否则会接收所有后续事件
- ACTION_DOWN
- ACTION_MOVE
做判断 返回是否拦截
- ACTION_MOVE
- ACTION_UP
不拦截,拦截了可能导致子控件up事件没收到,点击的up条件无法满足
- ACTION_UP
2.内部拦截法
- 要求父容器onInterceptTouchEvent 不能拦截down事件 。
事件处理都不能拦截down,ACTION_DOWN事件不受FLAG_DISALLOW_INTERCEPT标志位的影响
- 要求父容器onInterceptTouchEvent 不能拦截down事件 。
-
- 子控件dispatchTouchEvent方法中
- ACTION_DOWN
parent.requestDisallowInterceptTouchEvent(true);
//请求父容器不拦截事件。 down事件处理 见上1
- ACTION_DOWN
- ACTION_MOVE
若判断到父容器需要此类点击事件
则将parent.request方法 置false,允许父控件拦截,否则一直是不允许拦截的
- ACTION_MOVE
- ACTION_UP
不处理
一直返回 return super.dispatchTouchEvent(event);
- ACTION_UP