努力第一弹,把事件分发弄明白,本文主要看考资料有
Android事件分发机制详解:史上最全面、最易懂
android中的事件传递和处理机制
一问:为什么要研究事件分发,事件分发对我们有什么帮助?
原因有二:
第一点:面试,做开发,难免会换工作,当面试官问你的时候,你如果支支吾吾答不上来,想必对你的印象会大打折扣
第二点:开发中的应用,例如一些滑动嵌套,掌握了事件分发,分分钟解决问题
既然我们已经知道了事件分发是非常有意义的知识点,那么下一步就是学习它
二问:事件分发的对象是谁?
答:点击事件(Touch事件)
定义:
当用户触摸屏幕时(View或ViewGroup派生的控件),将产生点击事件(Touch事件)
Touch事件的相关细节(发生触摸的位置、时间等)被封装成MotionEvent对象
事件类型(4种)
事件类型具体动作
MotionEvent.ACTION_DOWN按下View(所有事件的开始)
MotionEvent.ACTION_UP抬起View(与DOWN对应)
MotionEvent.ACTION_MOVE滑动View
MotionEvent.ACTION_CANCEL结束事件(非人为原因)
三问:事件分发的本质
答:将点击事件(MotionEvent)传递到某个具体的View& 处理的整个过程
即 事件传递的过程 = 分发过程。
四问:事件在哪些对象之间进行传递?
答:Activity、ViewGroup、View
五问:事件分发过程由哪些方法协作完成?
答:dispatchTouchEvent() 、onInterceptTouchEvent()和onTouchEvent()
经过以上五问以后,我们大概应该对事件分发有个大体的了解了,下面我们就去看一下,事件分发是如何分发的
一:Activity的事件分发机制
当一个点击事件发生时,事件最先传到Activity的dispatchTouchEvent()进行事件分发
源码分析:
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
//这个方法是按下的时候执行,所以一定会执行,一个空方法而已
当此activity在栈顶时,触屏点击按home,back,menu键等都会触发此方法,可以忽略
onUserInteraction();
}
//这句话实现了从Activity向ViewGroup传递了,(分析一)
if (getWindow().superDispatchTouchEvent(ev)) {
return true;
}
return onTouchEvent(ev);
}
分析一:
为什么说这句话实现了从Activity向ViewGroup传递了呢?
因为window的实现类是PhoneWindow,而PhoneWindow的superDispatchTouchEvent方法返回 mDecor.superDispatchTouchEvent(event);
b. DecorView继承自FrameLayout,是所有界面的父类
c. FrameLayout是ViewGroup的子类,故DecorView的间接父类 = ViewGroup
image那么,ViewGroup的dispatchTouchEvent()什么时候返回true/false?请继续往下看ViewGroup事件的分发机制
二:ViewGroup事件的分发机制
从上面Activity事件分发机制可知,ViewGroup事件分发机制从dispatchTouchEvent()开始
源码分析:
//仅贴出关键代码,省略无用部分
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
// 分析一
if (!canceled && !**intercepted**) {
// 通过for循环,遍历了当前ViewGroup下的所有子View
for (int i = childrenCount -1; i >=0; i--) {
//分析二
if (**dispatchTransformedTouchEvent**(ev, false, child, idBitsToAssign)) {
......
break;
}}}}
分析一:
intercepted 是onInterceptTouchEvent()的返回值
a. 若在onInterceptTouchEvent()中返回false(即不拦截事件),就会让第二个值为true,从而进入到条件判断的内部
b. 若在onInterceptTouchEvent()中返回true(即拦截事件),就会让第二个值为false,从而跳出了这个条件判断
分析二:dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)方法内部调用了child.dispatchTouchEvent(event);
从而实现了事件从ViewGroup到View的传递
image三:View事件的分发机制
源码分析:
public boolean dispatchTouchEvent(MotionEvent event) {
分析一
if (li !=null && li.mOnTouchListener !=null
&& (mViewFlags &ENABLED_MASK) ==ENABLED
&& li.mOnTouchListener.onTouch(this, event)) {
result =true;
}
分析二
if (!result && onTouchEvent(event)) {
result =true;
}
return result;
}
分析一:
满足这三个条件就返回true,否则向下进行,其中最后一个条件是由mOnTouchListener提供者返回值,例如:
button.setOnTouchListener(new OnTouchListener(){
@Override
public boolean onTouch (View v , Motion Eventevent){
return false;
}});
分析二:
调用onTouchEvent(event),结果为true则返回true,onTouchEvent方法中会执行OnClick()方法
image
网友评论