本质:当点击事件(MotionEvent)向某个View进行传递并最终得到处理,
顺序:Activity(Window) ->ViewGroup->View
其中:View为具体的UI控件,例如Button
ViewGroup是容纳UI组件的容器,即一组View的集合,可以包含viewGroup和view,例如:LinearLayout
方法:
截屏2020-08-14 下午3.17.08.png
1.dispatchTouchEvent
使用对象:Activity、viewGroup、View
作用:分发点击事件
调用时刻:当点击事件能够传递给当前View时,该方法就会被调用
当返回true时:即在当前的对象消费事件,不会向下传递
当返回false时:当前对象不消费事件,不会向下传递事件,将事件回传给父类的onTouchEvent处理
2.onTouchEvent
使用对象:activity、ViewGroup、View
作用:处理点击事件
调用时刻:在dispatchTouchEvent内部调用
返回true:自己处理事件,不向下传递
返回false:不处理事件,调用父类的TouchEvent来处理事件
3.onInterceptTouchEvent
使用对象:ViewGroup
作用:拦截事件,即自己处理事件
调用时刻:在dispatchTouchEvent内部调用
返回true:调用当前对象的onTouchEvent去处理事件
返回false:继续分发事件
源码分析:
activity的dispatchTouchEvent
public boolean dispatchTouchEvent(MotionEvent ev) { //关注点1
//一般事件列开始都是DOWN,所以这里基本是true
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
//关注点2
onUserInteraction(); //空方法,主要用于屏保
}
//关注点3
if (getWindow().superDispatchTouchEvent(ev)) {
return true;
}
return onTouchEvent(ev);
}
@Override
public boolean superDispatchTouchEvent(MotionEvent event) {
return mDecor.superDispatchTouchEvent(event); //mDecor是DecorView的
实例
//DecorView是视图的顶层view,继承自FrameLayout,是所有界面的父类 }
public boolean superDispatchTouchEvent(MotionEvent event) { return
super.dispatchTouchEvent(event);
//DecorView继承自FrameLayout
//那么它的父类就是ViewGroup 而super.dispatchTouchEvent(event)方法,
其实就应该是ViewGroup的dispat chTouchEvent()
}
activity->viewGroup流程:
当一个点击事件发生
1.acitivity的dispatchTouchEvent()进行事件分发
2.调用getWindow得到phoneWindow的superDispatchTouchEvent();
3.上面那个方法是调用了DecorView的superPathTouchEvent方法
4.DecorView的父类属于ViewGroup.dispatchTouchEvent();
viewGroup->view
1.通过onInterceptTouchEvent方法返回true代表不拦截事件,即不允许事件继续向子view传递
2.返回false代表不拦截事件,即允许事件继续向子view传递
3.子view中如果将传递的事件消费掉,viewGroup将无法收到任何事件
view的dispatchTouchEvent
1.onTouch()的执行高于onClick
2.当控件被点击时:
2.1如果onTouch里返回false,会让dispatchTouchEvent返回false,就会执行onTouchEvent,如果setOnClickListener之后会回调onClick
2.2如果onTouch返回true,就会返回true,那么dispatchTouchEvent返回true;,那么久不会执行onTouchEvent,就不会执行onClick
网友评论