参考文献:Android事件分发机制详解:史上最全面、最易懂
事件分发的基础认识
1.事件分发的本质
将点击事件(MotionEvent)传递到某个具体的View & 处理的整个过程。
2.事件分发的顺序
Activity→viewgroup→view
3.事件分发的方法
dispatchTouchEvent() 、onInterceptTouchEvent()和onTouchEvent()
现在我们把这个过程通俗的理解一下:
我们把点击事件当做一个任务,activity是老板,viewgroup是你所在的团队,view则是你;经理、团队和你都可以下达任务,且都能自己完成,只有团队在下达任务的时候回考虑任务是否被拦截,也就是是否被完成。
事件分发的三部曲
1.activity的事件分发
按照我们给的通俗知识,继续理解一下:
下达任务
第一种清空:经理默认你的团队继续下达任务;
第二种情况:经理分配任务给团队,团队在分发任务的时候遇到了问题,你们团队炸毛了,不干了,经理自己干了;
第三种情况:经理下达任务成功,因为团队下达任务成功或任务被完成了,其实就是任务被完成了,继续下达,直到被完成;
第四种情况:经理直接自己干了
完成任务
第一种情况:任务不属于经理的工作范围内,但接受了,还是干了
第二种情况:任务不属于经理的工作范围内,不干了
2.viewgroup的事件分发
按照我们给的通俗知识,继续理解一下:
下达任务
第一种情况:团队接到任务,讨论一下,能不能完成,不能完成推回去,能完成就干
第二种情况:你或者其他团队成员下达给自己且完成任务了
第三种情况:团队给推回去了
拦截任务
第一种情况:团队讨论实现不了,推回去
第二种情况:能实现,继续下达,给你或者团队的其他人
完成任务
第一种情况:团队完成任务
第二种情况:团队不完成,退给经理
3.view的事件分发
下达任务
第一种情况:你接到任务,任劳任怨,完成
第二种情况:团队分发给别人,已经完成了
第三种情况:你自己不干,退给整个团队
完成任务
第一种情况:你完成任务
第二种情况:你不完成,推了且这个任务再也不接了
事件分发的实例
简单demo
布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/my_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:focusableInTouchMode="true"
android:orientation="vertical">
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="按钮1" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="按钮2" />
</LinearLayout>
核心代码:
package learn.yfg.com.dbdhtest;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
public class VGSJFFActivity extends AppCompatActivity {
Button button1,button2;
LinearLayout myLayout;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_vgsjff);
button1 = (Button)findViewById(R.id.button1);
button2 = (Button)findViewById(R.id.button2);
myLayout = (LinearLayout)findViewById(R.id.my_layout);
// 1.为ViewGroup布局设置监听事件
myLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("TAG", "点击了ViewGroup");
}
});
// 2. 为按钮1设置监听事件
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("TAG", "点击了button1");
}
});
// 3. 为按钮2设置监听事件
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("TAG", "点击了button2");
}
});
}
}
我们点击button,再点击空白处,打开对应日志,这一切看起来那么自然,但这里面就涉及了事件分发机制,我们来理解一下:
我们点击了button,这个事件优先传递到viewgroup,也就是myLayout,然后它又传递到具体的view,也就是button,这时候打印出了log,只有点击了button,并没有点击了viewgroup,原因是这个事件最终被button完成了。当我们点击空白处时,事件最终被viewgroup完成了。
按照我们签的说法再理解一下,经理下达了任务,首先经手团队,最后由你完成了,所以是你说完成了,不是团队完成了。这个任务不是你完成的,当然不用你说完成了,团队说下就ok了。
其他验证可以参考原文的实例。