触摸事件的分发机制
安卓的UI界面是一种树形壮结构的。层层嵌套组件,既然是很多组件嵌套在一起,倘若组件之间层层叠加,都有各自的触摸事件,当我们点击的时候,就不知道是哪个组件做出的响应。所以有了事件的分发机制。
主要有三个方法:
dispatchTouchEvent()
onTouchEvent()
onInterceptEvent()
用代码来实际演示各自代表什么意思。
图片来自http://www.jianshu.com/p/38015afcdb58
Demo
我自定义了一个ViewGroup继承自FrameLayout,里面包含这ChildView这个子空间,最外面则是Activity。
为了避免重复的代码,我写了一个工具类。
public class TouchUtil {
public static void logTouch(MotionEvent event, String name) {
int action = event.getAction();
switch (action){
case MotionEvent.ACTION_DOWN:
Log.i("does",name+"ACTION_DOWN 响应");
break;
case MotionEvent.ACTION_UP:
Log.i("does",name+"ACTION_UP 响应");
break;
case MotionEvent.ACTION_MOVE:
Log.i("does",name+"ACTION_MOVE 响应");
break;
}
}
}
ParentView
public class ParentViewGroup extends FrameLayout {
public ParentViewGroup(@NonNull Context context) {
super(context);
}
public ParentViewGroup(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
TouchUtil.logTouch(event,"ParentView onTouchEvent -------");
return super.onTouchEvent(event);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
TouchUtil.logTouch(ev,"Dispatch ParentView ---------");
// return super.dispatchTouchEvent(ev);
return super.dispatchTouchEvent(ev);
}
}
ChildView
public class ChildView extends View {
public ChildView(Context context) {
super(context);
}
public ChildView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
TouchUtil.logTouch(event,"ChildView onTouchEvent -------");
return super.onTouchEvent(event);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
TouchUtil.logTouch(ev,"Dispatch childView---------");
return super.dispatchTouchEvent(ev);
}
}
MainActivity
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
TouchUtil.logTouch(event,"MainActivity onTouchEvent -------");
return super.onTouchEvent(event);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
TouchUtil.logTouch(ev,"Dispatch Activity --------");
return super.dispatchTouchEvent(ev);
}
}
布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#f00"
tools:context="com.example.touch.MainActivity">
<com.example.touch.ParentViewGroup
android:layout_width="300dp"
android:layout_centerInParent="true"
android:layout_height="300dp"
android:background="#0f0"
>
<com.example.touch.ChildView
android:layout_gravity="center"
android:background="#00f"
android:layout_width="150dp"
android:layout_height="150dp" />
</com.example.touch.ParentViewGroup>
</RelativeLayout>
当我们运行程序的时候会,当我们点击ChildView的时候,输出日志信息,
08-25 05:34:28.599 31190-31190/com.example.touch I/does: Dispatch Activity ——–ACTION_DOWN 响应
08-25 05:34:28.600 31190-31190/com.example.touch I/does: Dispatch ParentView ———ACTION_DOWN 响应
08-25 05:34:28.600 31190-31190/com.example.touch I/does: Dispatch childView———ACTION_DOWN 响应
08-25 05:34:28.600 31190-31190/com.example.touch I/does: ChildView onTouchEvent ——-ACTION_DOWN 响应
08-25 05:34:28.600 31190-31190/com.example.touch I/does: ParentView onTouchEvent ——-ACTION_DOWN 响应
08-25 05:34:28.600 31190-31190/com.example.touch I/does: MainActivity onTouchEvent ——-ACTION_DOWN 响应
08-25 05:34:28.695 31190-31190/com.example.touch I/does: Dispatch Activity ——–ACTION_UP 响应
08-25 05:34:28.695 31190-31190/com.example.touch I/does: MainActivity onTouchEvent ——-ACTION_UP 响应
从上面Log日志当中我们可以知道。
dispatchEvent表示的是事件的一个分发机制方法,表示从外向里分发事件。默认返回为false,所以先执行dispatch事件。
当事件分发结束之后,处理TouchEvent事件,触摸事件则向上传递。默认返回的值为false。
onInterceptTouchEvent
这个函数代表的是拦截事件,顾名思义,默认返回的就是false,如果返回为true说明在当前view上进行拦截触摸事件。比如我在ParentView重写onInterceptTouchEvent方法并返回为true,则表示事件不再往下传递,通俗来说就是没ChildView什么事情了。但是这需要注意的是,只有viewGroup才有!!
这三个方法,用一个表格来说明
图片来自http://www.jianshu.com/p/38015afcdb58