1.自定义ViewGroup、View
首先自定义一个父容器CustomRelativeLayout,和一个子view:CustomView,并重写父容器的dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent,重写子View的dispatchTouchEvent、onTouchEvent,以及MainActivity的onTouchEvent,接着进行试验:
布局代码如下:
<?xml version="1.0" encoding="utf-8"?>
<com.example.wjc.eventdispatch.CustomRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.wjc.eventdispatch.CustomView
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_centerInParent="true"
android:background="@color/colorPrimary" />
</com.example.wjc.eventdispatch.CustomRelativeLayout>
1.重写的方法一律返回它们的super方法
返回都是false,点击自定义view后执行顺序如下:
- VG:dispatchTouchEvent
- VG:onInterceptTouchEvent执行并返回false
- V:dispatchTouchEvent
- V:onTouchEvent执行并返回false
- V:dispatchTouchEvent返回false
- VG:onTouchEvent执行并返回false
- VG:dispatchTouchEvent返回false
- MainActivity:onTouchEvent返回false
其中VG代表自定义ViewGroup即CustomRelativeLayout,V代表自定义View:CustomView
由上可清晰看出view事件的分发顺序即规则:即从布局中的根布局的dispatchTouchEvent开始,如果onInterceptTouchEvent返回为true,代表拦截事件,则执行onTouchEvent,而且事件不在向下分发;否则继续向下分发执行子View的dispatchTouchEvent,以此类推,直到最后的view,分发规则如下伪代码:
public boolean dispatchTouchEvent(MotionEvent ev) {
boolean isDispatch;
if(onInterceptTouchEvent(ev)){
isDispatch=onTouchEvent(ev);
}else {
isDispatch=childView.dispatchTouchEvent(ev);
}
return isDispatch;
}
事件传递到最下面的view后会执行view的onTouchEvent方法,若该方法返回true则表示处理该事件,接着该view的dispatchTouchEvent返回true,再往上一层一层回调dispatchTouchEvent并返回true;
若事件传递到最下面的view后执行view的onTouchEvent方法返回false,代表不处理该事件,则会回调上层view的onTouchEvent和dispatchTouchEvent,以此类推,直到Activity里的onTouchEvent。
而且一旦view对事件不处理,则对之后该事件的其他动作均不处理。