在结合资料和项目开发过程中遇到的问题(更多好内容戳下面:https://blog.csdn.net/wuqingsen1),下面是本人对 Android 事件分发机制的了解:
1. 事件分发的对象是谁?
答:点击事件( Touch 事件 )。Touch 事件的相关细节(发生触摸的位置、时间等)被封装成 MotionEvent 对象。
2.事件的类型分为几种?
答:分为四种,具体如下表;
事件类型 | 具体动作 |
MotionEvent.ACTION_DOWN | 按下 View (所有事件的开始) |
MotionEvent.ACTION_UP | 抬起 View |
MotionEvent.ACTION_MOVE | 滑动 View |
MotionEvent.ACTION_CANCEL | 结束事件 (非人为原因) |
3.事件列:手指触摸屏幕到离开屏幕这个过程产生的一系列事件如下;
3.事件在哪些对象之间进行传递?
答:Activity、ViewGroup、View( Android 的 UI 界面 Activity、ViewGroup、View 以及派生类组成)。
4.事件的分发顺序?
答:即事件的传递顺序:Activity ==> ViewGroup ==> View 。
5.事件分发过程由哪些主要方法协作完成?
答:dispatchTouchEvent()、onInterceptTouchEvent() 和 onTouchEvent() 。( 下面是对三个方法的介绍 )
方法 | 名称 | 作用 | 调用时刻 |
dispatchTouchEvent() | 分发事件 | 分发传递事件 | 当点击事件能够传递给当前 View 时,该方法会被调用 |
onInterceptTouchEvent() | 拦截事件 | 判断是否拦截了事件; 默认返回 false 表示不拦截该事件,事件将向下传递(传递给其子View); | 在 dispatchTouchEvent() 内部调用 |
onTouchEvent() | 触摸事件 | 处理点击事件; 返回true则表示该View能处理该事件,事件将终止向上传递(传递给其父View); | 在 ViewGroup 的 dispatchTouchEvent() 内部调用; |
下面是拥有这三个方法的对象:
对象名称 | 例子 | 方法名称 |
Activity | Activity | dispatchTouchEvent(); onTouchEvent(); |
ViewGroup | LinearLayout | dispatchTouchEvent(); onInterceptTouchEvent(); onTouchEvent(); |
View | TextView | dispatchTouchEvent(); onTouchEvent(); |
6.工作流程的总结:
7.核心方法的总结:
8.Demo(demo下载地址https://download.csdn.net/download/wuqingsen1/10635286):
//Activity 即第一层
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.e("e", "第一层 dispatchTouchEvent ACTION_DOWN");
break;
case MotionEvent.ACTION_UP:
Log.e("e", "第一层 dispatchTouchEvent ACTION_UP");
break;
default:
break;
}
Log.e("e", "第一层" + "往下分派事件");
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.e("e", "第一层 onTouchEvent ACTION_DOWN");
break;
case MotionEvent.ACTION_UP:
Log.e("e", "第一层 onTouchEvent ACTION_UP");
break;
default:
break;
}
boolean t = false;
Log.e("e", "第一层" + "能解决吗" + t);
return t;
}
}
//ViewGroup 即第二层
public class MyLinearLayout extends LinearLayout {
public MyLinearLayout(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.e("e", "第二层 dispatchTouchEvent ACTION_DOWN");
break;
case MotionEvent.ACTION_UP:
Log.e("e", "第二层 dispatchTouchEvent ACTION_UP");
break;
default:
break;
}
Log.e("e", "第二层" + "往下分派事件");
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.e("e", "第二层 onInterceptTouchEvent ACTION_DOWN");
break;
case MotionEvent.ACTION_UP:
Log.e("e", "第二层 onInterceptTouchEvent ACTION_UP");
break;
default:
break;
}
boolean b = false;
Log.e("e", "第二层" + "需要拦截吗" + b);
return b;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.e("e", "第二层 onTouchEvent ACTION_DOWN");
break;
case MotionEvent.ACTION_UP:
Log.e("e", "第二层 onTouchEvent ACTION_UP");
break;
default:
break;
}
boolean b = false;
Log.e("e", "第二层" + "能解决吗" + b);
return b;
}
}
//View 即第三层
@SuppressLint("AppCompatCustomView")
public class MyTextView extends TextView{
public MyTextView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()){
case MotionEvent.ACTION_DOWN:
Log.e("e","第三层 dispatchTouchEvent ACTION_DOWN");
break;
case MotionEvent.ACTION_UP:
Log.e("e","第三层 dispatchTouchEvent ACTION_UP");
break;
default:
break;
}
Log.e("e", "第三层"+"往下分派事件?我是最底层,没有办法分派事件");
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()){
case MotionEvent.ACTION_DOWN:
Log.e("e","第三层 onTouchEvent ACTION_DOWN");
break;
case MotionEvent.ACTION_UP:
Log.e("e","第三层 onTouchEvent ACTION_UP");
break;
default:
break;
}
boolean b = false;
Log.e("e", "第三层"+"能解决吗"+b);
return b;
}
}
下面是分发走的顺序:
至此,应该对事件分发机制有一定了解,demo下载地址https://download.csdn.net/download/wuqingsen1/10635286。
如果有更好的见解或补充点下面喔: