android的事件处理机制,相信很多人一开始都比较难懂,如果单单在官网上看流程图,你肯定会很快忘记。那么,遇到比较难懂的知识点,你会怎么做呢?
一是看源码,然后就是写实例加深理解。我选择后者,哈哈,我这里只是想说,如何快速的带大家了解事件处理和传递机制。
那么废话不多说,先把代码贴出来,不懂的地方,大家不妨手把手写代码,多试试。
1.新建一个activity,调出dispatchTouchEvent和onTouchEvent方法。
public class EventTestAct extends Activity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.event_test);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
Log.e("xx", "act dispatchTouchEvent");
}
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
Log.e("xx", "act onTouchEvent");
}
return super.onTouchEvent(event);
}
}
2.新增两个自定义ViewGroup。调用dispatchTouchEvent,onInterceptTouchEvent,onTouchEvent方法。
public class MyViewGroup1 extends LinearLayout {
public MyViewGroup1(Context context) {
super(context);
}
public MyViewGroup1(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public MyViewGroup1(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
Log.e("xx", "vp1 dispatchTouchEvent");
}
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
Log.e("xx", "vp1 onInterceptTouchEvent");
}
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.e("xx", "vp1 onTouchEvent");
return super.onTouchEvent(event);
}
}
public class MyViewGroup2 extends LinearLayout {
public MyViewGroup2(Context context) {
super(context);
}
public MyViewGroup2(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public MyViewGroup2(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
Log.e("xx", "vp2 dispatchTouchEvent");
}
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
Log.e("xx", "vp2 onInterceptTouchEvent");
}
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
Log.e("xx", "vp2 onTouchEvent");
}
return super.onTouchEvent(event);
}
}
3.新建一个自定义view,调用dispatchTouchEvent和onTouchEvent方法。
public class MyView extends View {
public MyView(Context context) {
super(context);
}
public MyView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
Log.e("xx", "mv dispatchTouchEvent");
}
return super.dispatchTouchEvent(event);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
Log.e("xx", "mv onTouchEvent");
}
return super.onTouchEvent(event);
}
}
4.创建布局xml。
<?xml version="1.0" encoding="utf-8"?>
<com.kv.mymeet.event.MyViewGroup1 xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/vp1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.kv.mymeet.event.MyViewGroup2
android:id="@+id/vp2"
android:background="#ffffff"
android:layout_width="match_parent"
android:layout_height="300dp">
<com.kv.mymeet.event.MyView
android:id="@+id/mv"
android:background="#ab4a4a"
android:layout_width="match_parent"
android:layout_height="50dp" />
</com.kv.mymeet.event.MyViewGroup2>
</com.kv.mymeet.event.MyViewGroup1>
我们试着写这样一个demo,然后监听action down这个事件,再在上面写上日志。通过修改回调,我们可以观察出事件的传递顺序。
1.什么都没改的情况下做点击,出来的顺序是
12-29 14:55:55.609 4698-4698/com.kv.mymeet E/xx: act dispatchTouchEvent
12-29 14:55:55.619 4698-4698/com.kv.mymeet E/xx: vp1 dispatchTouchEvent
12-29 14:55:55.619 4698-4698/com.kv.mymeet E/xx: vp1 onInterceptTouchEvent
12-29 14:55:55.619 4698-4698/com.kv.mymeet E/xx: vp2 dispatchTouchEvent
12-29 14:55:55.619 4698-4698/com.kv.mymeet E/xx: vp2 onInterceptTouchEvent
12-29 14:55:55.619 4698-4698/com.kv.mymeet E/xx: mv dispatchTouchEvent
12-29 14:55:55.619 4698-4698/com.kv.mymeet E/xx: mv onTouchEvent
12-29 14:55:55.619 4698-4698/com.kv.mymeet E/xx: vp2 onTouchEvent
12-29 14:55:55.619 4698-4698/com.kv.mymeet E/xx: vp1 onTouchEvent
12-29 14:55:55.619 4698-4698/com.kv.mymeet E/xx: act onTouchEvent
可以看得出,事件做从父类做分发,dispatchTouchEvent方法。然后再执行onTouchEvent方法,而onTouchEvent是从子类向父类传。
2.下面我们来操作dispatchTouchEvent方法。
情况1,activity,无论修改dispatchTouchEvent返回值是true或者false,事件都不会再往下面做传递,onTouchEvent的方法均不会触发。(activity层的dispatchTouchEvent方法一般都不会去改)
12-29 15:16:22.719 12659-12659/com.kv.mymeet E/xx: act dispatchTouchEvent
情况2,ViewGroup1层,dispatchTouchEvent返回值为true,事件都不会再往下面做传递,onTouchEvent的方法均不会触发。
12-29 17:11:24.381 8772-8772/com.kv.mymeet E/xx: act dispatchTouchEvent
12-29 17:11:24.391 8772-8772/com.kv.mymeet E/xx: vp1 dispatchTouchEvent
情况3,ViewGroup1层,dispatchTouchEvent返回值为false,事件都不会再往下面做传递,activity层的onTouchEvent方法会触发。
12-30 00:58:05.396 5402-5402/com.kv.mymeet E/xx: act dispatchTouchEvent
12-30 00:58:05.397 5402-5402/com.kv.mymeet E/xx: vp1 dispatchTouchEvent
12-30 00:58:05.398 5402-5402/com.kv.mymeet E/xx: act onTouchEvent
情况4,ViewGroup2层,dispatchTouchEvent返回值为true,事件都不会再往下面做传递,onTouchEvent的方法均不会触发。
12-30 01:05:01.820 6759-6759/com.kv.mymeet E/xx: act dispatchTouchEvent
12-30 01:05:01.821 6759-6759/com.kv.mymeet E/xx: vp1 dispatchTouchEvent
12-30 01:05:01.821 6759-6759/com.kv.mymeet E/xx: vp1 onInterceptTouchEvent
12-30 01:05:01.821 6759-6759/com.kv.mymeet E/xx: vp2 dispatchTouchEvent
情况5,ViewGroup2层,dispatchTouchEvent返回值为false,事件都不会再往下面做传递,activity层和viewgoup1层的onTouchEvent方法会触发。
12-30 01:07:47.201 6759-6759/com.kv.mymeet E/xx: act dispatchTouchEvent
12-30 01:07:47.201 6759-6759/com.kv.mymeet E/xx: vp1 dispatchTouchEvent
12-30 01:07:47.201 6759-6759/com.kv.mymeet E/xx: vp1 onInterceptTouchEvent
12-30 01:07:47.202 6759-6759/com.kv.mymeet E/xx: vp2 dispatchTouchEvent
12-30 01:07:47.203 6759-6759/com.kv.mymeet E/xx: vp1 onTouchEvent
12-30 01:07:47.203 6759-6759/com.kv.mymeet E/xx: act onTouchEvent
情况6,view层,dispatchTouchEvent返回值为true,事件都不会再往下面做传递,onTouchEvent的方法均不会触发。(如果想触发ontouchEvent方法,一般子view和父容器的dispatchTouchEvent均不为true)
12-30 01:19:12.317 7991-7991/com.kv.mymeet E/xx: act dispatchTouchEvent
12-30 01:19:12.318 7991-7991/com.kv.mymeet E/xx: vp1 dispatchTouchEvent
12-30 01:19:12.318 7991-7991/com.kv.mymeet E/xx: vp1 onInterceptTouchEvent
12-30 01:19:12.318 7991-7991/com.kv.mymeet E/xx: vp2 dispatchTouchEvent
12-30 01:19:12.319 7991-7991/com.kv.mymeet E/xx: vp2 onInterceptTouchEvent
12-30 01:19:12.319 7991-7991/com.kv.mymeet E/xx: mv dispatchTouchEvent
12-30 01:10:05.237 7426-7426/com.kv.mymeet E/xx: act dispatchTouchEvent
12-30 01:10:05.238 7426-7426/com.kv.mymeet E/xx: vp1 dispatchTouchEvent
12-30 01:10:05.238 7426-7426/com.kv.mymeet E/xx: vp1 onInterceptTouchEvent
12-30 01:10:05.238 7426-7426/com.kv.mymeet E/xx: vp2 dispatchTouchEvent
12-30 01:10:05.238 7426-7426/com.kv.mymeet E/xx: vp2 onInterceptTouchEvent
12-30 01:10:05.238 7426-7426/com.kv.mymeet E/xx: mv dispatchTouchEvent
12-30 01:10:05.239 7426-7426/com.kv.mymeet E/xx: vp2 onTouchEvent
12-30 01:10:05.239 7426-7426/com.kv.mymeet E/xx: vp1 onTouchEvent
12-30 01:10:05.240 7426-7426/com.kv.mymeet E/xx: act onTouchEvent
3.下面我们来操作viewgroup的onInterceptTouchEvent方法。
情况1,viewgroup1层onInterceptTouchEvent返回值为true,事件传递在这一层终止,ontouchEvent也在这一层终止。
12-30 12:38:13.655 21700-21700/com.kv.mymeet E/xx: act dispatchTouchEvent
12-30 12:38:13.656 21700-21700/com.kv.mymeet E/xx: vp1 dispatchTouchEvent
12-30 12:38:13.656 21700-21700/com.kv.mymeet E/xx: vp1 onInterceptTouchEvent
12-30 12:38:13.656 21700-21700/com.kv.mymeet E/xx: vp1 onTouchEvent
12-30 12:38:13.657 21700-21700/com.kv.mymeet E/xx: act onTouchEvent
情况2,viewgroup1层onInterceptTouchEvent返回值为false,事件传递正常,ontouchEvent也正常传递。
12-30 12:40:48.535 21700-21700/com.kv.mymeet E/xx: act dispatchTouchEvent
12-30 12:40:48.535 21700-21700/com.kv.mymeet E/xx: vp1 dispatchTouchEvent
12-30 12:40:48.536 21700-21700/com.kv.mymeet E/xx: vp1 onInterceptTouchEvent
12-30 12:40:48.536 21700-21700/com.kv.mymeet E/xx: vp2 dispatchTouchEvent
12-30 12:40:48.536 21700-21700/com.kv.mymeet E/xx: vp2 onInterceptTouchEvent
12-30 12:40:48.536 21700-21700/com.kv.mymeet E/xx: mv dispatchTouchEvent
12-30 12:40:48.536 21700-21700/com.kv.mymeet E/xx: mv onTouchEvent
12-30 12:40:48.537 21700-21700/com.kv.mymeet E/xx: vp2 onTouchEvent
12-30 12:40:48.537 21700-21700/com.kv.mymeet E/xx: vp1 onTouchEvent
12-30 12:40:48.538 21700-21700/com.kv.mymeet E/xx: act onTouchEvent
情况3,
viewgroup2层onInterceptTouchEvent返回值为true,事件传递在这一层终止,ontouchEvent也在这一层终止。(想让父容器的子view不触发事件,可设onInterceptTouchEvent返回值为true)
12-30 12:42:37.399 22347-22347/com.kv.mymeet E/xx: act dispatchTouchEvent
12-30 12:42:37.399 22347-22347/com.kv.mymeet E/xx: vp1 dispatchTouchEvent
12-30 12:42:37.399 22347-22347/com.kv.mymeet E/xx: vp1 onInterceptTouchEvent
12-30 12:42:37.399 22347-22347/com.kv.mymeet E/xx: vp2 dispatchTouchEvent
12-30 12:42:37.399 22347-22347/com.kv.mymeet E/xx: vp2 onInterceptTouchEvent
12-30 12:42:37.400 22347-22347/com.kv.mymeet E/xx: vp2 onTouchEvent
12-30 12:42:37.400 22347-22347/com.kv.mymeet E/xx: vp1 onTouchEvent
12-30 12:42:37.400 22347-22347/com.kv.mymeet E/xx: act onTouchEvent
3.
下面我们来操作viewgroup的onTouchEvent方法。
情况1,view层,设置onTouchEvent值为true,事件在这一层被消费,不向上传递。
12-30 12:51:24.742 23131-23131/com.kv.mymeet E/xx: act dispatchTouchEvent
12-30 12:51:24.742 23131-23131/com.kv.mymeet E/xx: vp1 dispatchTouchEvent
12-30 12:51:24.743 23131-23131/com.kv.mymeet E/xx: vp1 onInterceptTouchEvent
12-30 12:51:24.743 23131-23131/com.kv.mymeet E/xx: vp2 dispatchTouchEvent
12-30 12:51:24.743 23131-23131/com.kv.mymeet E/xx: vp2 onInterceptTouchEvent
12-30 12:51:24.743 23131-23131/com.kv.mymeet E/xx: mv dispatchTouchEvent
12-30 12:51:24.743 23131-23131/com.kv.mymeet E/xx: mv onTouchEvent
情况2,view层,设置onTouchEvent值为false,事件传递正常,ontouchEvent也正常传递。
12-30 12:54:38.713 23959-23959/com.kv.mymeet E/xx: act dispatchTouchEvent
12-30 12:54:38.714 23959-23959/com.kv.mymeet E/xx: vp1 dispatchTouchEvent
12-30 12:54:38.715 23959-23959/com.kv.mymeet E/xx: vp1 onInterceptTouchEvent
12-30 12:54:38.715 23959-23959/com.kv.mymeet E/xx: vp2 dispatchTouchEvent
12-30 12:54:38.715 23959-23959/com.kv.mymeet E/xx: vp2 onInterceptTouchEvent
12-30 12:54:38.715 23959-23959/com.kv.mymeet E/xx: mv dispatchTouchEvent
12-30 12:54:38.715 23959-23959/com.kv.mymeet E/xx: mv onTouchEvent
12-30 12:54:38.717 23959-23959/com.kv.mymeet E/xx: vp2 onTouchEvent
12-30 12:54:38.717 23959-23959/com.kv.mymeet E/xx: vp1 onTouchEvent
12-30 12:54:38.718 23959-23959/com.kv.mymeet E/xx: act onTouchEvent
情况3,viewgroup层,设置onTouchEvent值为true,事件在这一层被消费,不向上传递。
12-30 12:55:46.054 24256-24256/com.kv.mymeet E/xx: act dispatchTouchEvent
12-30 12:55:46.055 24256-24256/com.kv.mymeet E/xx: vp1 dispatchTouchEvent
12-30 12:55:46.055 24256-24256/com.kv.mymeet E/xx: vp1 onInterceptTouchEvent
12-30 12:55:46.055 24256-24256/com.kv.mymeet E/xx: vp2 dispatchTouchEvent
12-30 12:55:46.055 24256-24256/com.kv.mymeet E/xx: vp2 onInterceptTouchEvent
12-30 12:55:46.055 24256-24256/com.kv.mymeet E/xx: mv dispatchTouchEvent
12-30 12:55:46.056 24256-24256/com.kv.mymeet E/xx: mv onTouchEvent
12-30 12:55:46.056 24256-24256/com.kv.mymeet E/xx: vp2 onTouchEvent
情况4,viewgroup层,设置onTouchEvent值为false,事件传递正常,ontouchEvent也正常传递。
12-30 12:58:36.758 24256-24256/com.kv.mymeet E/xx: act dispatchTouchEvent
12-30 12:58:36.759 24256-24256/com.kv.mymeet E/xx: vp1 dispatchTouchEvent
12-30 12:58:36.759 24256-24256/com.kv.mymeet E/xx: vp1 onInterceptTouchEvent
12-30 12:58:36.759 24256-24256/com.kv.mymeet E/xx: vp2 dispatchTouchEvent
12-30 12:58:36.760 24256-24256/com.kv.mymeet E/xx: vp2 onInterceptTouchEvent
12-30 12:58:36.774 24256-24256/com.kv.mymeet E/xx: mv dispatchTouchEvent
12-30 12:58:36.774 24256-24256/com.kv.mymeet E/xx: mv onTouchEvent
12-30 12:58:36.775 24256-24256/com.kv.mymeet E/xx: vp2 onTouchEvent
12-30 12:58:36.775 24256-24256/com.kv.mymeet E/xx: vp1 onTouchEvent
12-30 12:58:36.776 24256-24256/com.kv.mymeet E/xx: act onTouchEvent
以上的试验,可以用画图直观的表现出来。