版权声明:本文来自门心叼龙的博客,属于原创内容,转载请注明出处:https://blog.csdn.net/geduo_83/article/details/90145083
github源码下载地址:https://github.com/geduo83/android-touch-event
Android事件分发机制的探索与发现之View篇
Android事件分发机制的探索与发现之ViewGroup篇
Android事件分发机制的探索与发现之Activity篇
Android事件分发机制的探索与发现之总结篇
Android事件分发机制在实战开发中的应用之一
Android事件分发机制在实战开发中的应用之二
前两篇我们主要研究了,View和ViewGourp的事件分发流程,今天我们主要来研究一些Activity的事件传递 流程。
实际上,当我们手指触摸屏幕的时候,事件最先是传递给当前的Actvity,由Actvity的dispatchTouchEvent方法来分发事件,而Actvity会将事件传递给Window对象来分发,Window对象再传递给Decor View,而Decor View则是我们在Actvity中通过setContentView后所设置的布局的父容器
当ACTION_DOWN事件的时候,会先执行onUserInteraction();而onUserInteraction()方法是个空方法,事实上,当此activity在栈顶时,我们触屏、点击、或者按home,back,menu键等都会触发此方法,所以onUserInteraction()可以用于屏保。
接下来调用getWindow().superDispatchTouchEvent(ev)去分发事件,如果最终事件被消耗了,则直接返回true,否则Activity才会调用onTouchEvent方法自己来处理事件。
getWindow()是一个window对象。而Window类是抽象类,从Window类的注释里面说明了PhoneWindow类是Window类的唯一实现类。然而PhoneWindow存在于框架层中,在sdk中是没有源码的,因此我们看不到。想要查看源码则必须手动关联PhoneWindow,请读者自行百度。
PhoneWindow类的superDispatchTouchEvent方法源码如下:
@Override
public boolean superDispatchTouchEvent(MotionEvent event) {
return mDecor.superDispatchTouchEvent(event);
}
说明window对象是把事件传给mDecor去分发,mDecor就是上面我们说的Decor View。Decor View的superDispatchTouchEvent源码如下:
public boolean superDispatchTouchEvent(MotionEvent event) {
return super.dispatchTouchEvent(event);
}
其实也是调用ViewGroup类的dispatchTouchEvent方法。
到了这里,我们已经验证了事件的传递是:Activity->Window->decor View->ViewGroup
其实到了Decor View这里就相当于事件传递到了我们在Activity中设置的布局父容器了
MainActivity的dispatchTouchEvent方法
- 情况1:调用了父类的同名方法
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.v(TAG,"MainActivity dispatchTouchEvent start:"+MotionEventUtil.getMotionEventName(ev));
return super.dispatchTouchEvent(ev);
}
测试结果:
V/MYTAG: MainActivity dispatchTouchEvent start:ACTION_DOWN
V/MYTAG: MyLayout dispatchTouchEvent start:ACTION_DOWN
V/MYTAG: MainActivity dispatchTouchEvent start:ACTION_UP
V/MYTAG: MyLayout dispatchTouchEvent start:ACTION_UP
情况2:返回true
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.v(TAG,"MainActivity dispatchTouchEvent start:"+MotionEventUtil.getMotionEventName(ev));
return true;
}
测试结果:
V/MYTAG: MainActivity dispatchTouchEvent start:ACTION_DOWN
V/MYTAG: MainActivity dispatchTouchEvent start:ACTION_UP
自行消费了
情况3:返回false
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.v(TAG,"MainActivity dispatchTouchEvent start:"+MotionEventUtil.getMotionEventName(ev));
return false;
}
测试结果:
V/MYTAG: MainActivity dispatchTouchEvent start:ACTION_DOWN
V/MYTAG: MainActivity dispatchTouchEvent start:ACTION_UP
其实也是应该回传给父级View了,只是我们现在没有办法进行追踪测试
好了,MainActivity就dispathTouchEvent方法也就分析完毕了,调用父类的同名方法则事件继续往下级View进行分发,如果返回true或者false则进行消费掉了,无论dispathTouchEvent返回什么值MainActivity的onTouchEvent方法永远不会被调用的,除非它下级子View的dispathTouchEvent方法或者onTouchEvent方法返回false,触摸事件才能回传给我们的MainActivity的onTouchEvent方法,才能引起MainActivity的onTouchEvent方法的调用
截止目前,关于Android事件传递机制的探索与发现,三篇文章我们就全部将完了