事件分发机制在安卓中非常重要,这个事情如果搞不懂,会困扰你很多事情。比如说,应用了github上的某个大神的库,如果发现这个库实现了你需求的80%,还有那么20%需要你结合实际需求来实现,改大神代码又不能改,怎么办呢?这个时候往往需要搞清楚自己的布局控件和第三方库的控件事件传递关系。说的比较模糊,没关系,只要知道事件传递必须学会,就ok了。
直接上图(图片较大,可右键标签页中打开,也可下载下来看):
图上已经标的很清楚了,所有返回情况一定要知道,这样的话,界面一些效果才能达到预期效果。如果想问这个事件传递自己怎么去验证我说的是对的,也简单的,自己定义几个view,嵌套布局即可,简单贴下代码:
<?xml version="1.0" encoding="utf-8"?>
<com.joyoung.eventdispatch.ActivityLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.joyoung.eventdispatch.MainActivity">
<com.joyoung.eventdispatch.ViewGroupLayout
android:layout_width="match_parent"
android:layout_height="200dp">
<com.joyoung.eventdispatch.MyViewLayout
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="100dp"
android:text="click me"
android:background="@color/colorAccent"
/>
</com.joyoung.eventdispatch.ViewGroupLayout>
</com.joyoung.eventdispatch.ActivityLayout>
public class ViewGroupLayout extends LinearLayout {
private final String TAG = ViewGroupLayout.class.getName();
public ViewGroupLayout(Context context) {
super(context);
}
public ViewGroupLayout(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public ViewGroupLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.e(TAG, "----dispatchTouchEvent---------" + ev.getAction());
return false;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.e(TAG, "----onInterceptTouchEvent---------" + ev.getAction());
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.e(TAG, "----onTouchEvent---------" + event.getAction());
return super.onTouchEvent(event);
}
}
public class MyViewLayout extends View {
private final String TAG = MyViewLayout.class.getName();
public MyViewLayout(Context context) {
super(context);
}
public MyViewLayout(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
Log.e(TAG, "----dispatchTouchEvent---------" + event.getAction());
return true;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.e(TAG, "----onTouchEvent---------" + event.getAction());
return false;
}
}
基本的分析就是如上代码所示,通过日志来分析事件传递的方向。最后总结一下:
- 如果从activity到viewgroup再到子view一路都是super的返回方式,表示不作任何处理,最后返回给上层的onTouchEvent处理,直到传递到activity,之后的事件也不会传递下来,直接在activity中通过dispatchTouchEvent的分发给onTouchEvent处理;
- activity和最终的子view中都没有事件拦截onInterceptTouchEvent;
- dispatchTouchEvent的super有着自己的意义,并不是简单的默认的false,如果是false的话,子view根本没机会处理时间;
- 最底层view的onTouchEvent返回true消费完,不反馈, 上层视图没有收到处理信息。返回false和返回super效果相同;
- activity的dispatchTouchEvent返回true和false事件都不会向下传递,只有返回super向下传递,也不会触发activity中的onTouchEvent方法;