事件分发对象:MotionEvent
系统把事件封装为MotionEvent对象,事件分发的过程就是MotionEvent分发的过程
事件类型:
按下:ACTION_DOWN
移动:ACTION_MOVE
抬起:ACTION_UP
取消:ACTION_CANCEL
事件序列:从手指按下屏幕开始,到手指离开屏幕所产生的一些列事件
传递层级:Activity -> Window -> DecorView -> ViewGroup -> View
源码阅读
Activity事件分发流程图
dispatchTouchEvent(MotionEvent event)
onTouchEvent(MotionEvent event)
ViewGroup事件分发流程图
1、去判断是否需要拦截事件
2、在当前ViewGroup中找到用户真正点击的View
3、分发事件到View上
dispatchTouchEvent(MotionEvent event)
onInterceptTouchEvent(MotionEvent event)
onTouchEvenet(MotionEvent event)
image.png
View事件分发流程图
dispatchTouchEvent(MotionEvent event)
onTouchEvenet(MotionEvent event)
image.png
验证事件分发流程:
正常情况下事件分发的流程如下:
image.png
同一个事件序列,如果子View(ViewGroup)没有处理该事件(没有消费事件),那么后续事件就不会再传递到子View中
ViewGroup拦截事件
public class MyViewGroup extends FrameLayout {
private static final String Log = "TouchEventDemo";
public MyViewGroup(@NonNull Context context) {
super(context);
}
public MyViewGroup(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public MyViewGroup(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
android.util.Log.d(Log, "MyViewGroup:dispatchTouchEvent");
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
android.util.Log.d(Log, "MyViewGroup:onInterceptTouchEvent");
super.onInterceptTouchEvent(ev);
return true;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// android.util.Log.d(Log, "MyViewGroup:onTouchEvent");
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
android.util.Log.d(Log, "MyViewGroup:手指按下");
break;
case MotionEvent.ACTION_MOVE:
android.util.Log.d(Log, "MyViewGroup:手指移动");
break;
case MotionEvent.ACTION_UP:
android.util.Log.d(Log, "MyViewGroup:手指抬起");
break;
}
super.onTouchEvent(event);
return true;
}
}
打印如下:
image.png
网友评论