关于 Android 的事件分发机制,自我感觉还是比较乱的,要弄懂是要费上一点功夫,网上有很多关于这方面的文章,我在学习的时候也看了一下些,但我还是想用自己的语言总结一下这部分的知识点。
首先有三个词:分发、拦截、消费。
在这之前,我们先简单的创建一个活动,
界面布局如下,自定义个 ViewGroup 继承于 RelativeLayout 自定义一个 View 继承于TextView
为什么不直接使用 RelativeLayout 和 TextView 呢?
因为接下来要为这两个控件和 MainActivity 都重写 onTouchEvent() 方法,并且打印Log
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.e("MyLayout","onTouchEvent");
return super.onTouchEvent(event);
}
//MyTextView和MainActivity同理
Log打印如下:
分析一下:可以看出触摸事件是从 MyText 开始的 再 传递给 MyLayout 最后回到 MainActivity。那为什么不是从 MainActivity 开始的呢?这个就涉及到事件的 分发机制 了
我们还是先从简单消费机制着手
我们会发现 onTouchEvent() 这个方法是有返回值的,这个返回值是干什么用的呢?
尝试把 MyText 的 onTouchEvent() 返回值改成 true:
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.e("MyText","onTouchEvent");
return true;
}
再次打印Log:
发现只打印了 MyText 的 onTouchEvent 了,这是因为 这个事件被 MyText 消费了,所以 return true 就代表消费事件,事件将不会在往上传递!
返回 false :表示不消费此事件,如果都不消费最终会由 MainActivity 消费
接着讲讲 分发:
接着为这两个控件和MainActivity添加 dispathchTouchEvent() 方法,并且打印Log
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
Log.e("MyText","dispatchTouchEvent");
return super.dispatchTouchEvent(event);
}
Log打印如下:
对比一下上次打印的信息,发现 dispathchTouchEvent() 是从MainActiviy开始往下传递的,这就是事件的分发方法
事件从顶层开始往底层分发,最后从底层的触摸事件传递回顶层。
观察一下 dispathchTouchEvent() 方法,发现这个方法也是有返回值的
尝试把 MyLayout 的 dispathchTouchEvent() 方法的返回值改为 true
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
Log.e("MainActivity","dispatchTouchEvent");
return true;
}
看一眼Log打印信息:
跟 消费 是同样的道理,如果返回 true 则不再往下分发事件,并且消费事件。
那试试返回 false,修改 MyLayout 中的 dispatchTouchEvent() 方法返回值为 false
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
Log.e("MyLayout","dispatchTouchEvent");
return false;
}
对比一下 返回 true 的情况,发现返回 false 就不会把事件消费掉,而是直接往上传递。
分发 也就到这里结束了。
最后在讲一讲 拦截。
拦截 是这个方法:onInterceptTouchEvent() 只有 ViewGroup 才能使用拦截。那么在 MyLayout 中重写这个方法并打印Log:
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.e("MyLayout","onInterceptTouchEvent");
return super.onInterceptTouchEvent(ev);
}
这个方法会在 分发后被调用,那么拦截是来做什么的呢?
我们把 返回值改为 true,再看一眼Log打印
对比一下分发的情况,发现 MyLayout 的 onTouchEvent 也被执行了!这就是拦截和分发的区别。
返回false 的话则表示不拦截,事件会接着传递。
那么整个 Android 的事件传递机制到这就基本讲完了。最后在文尾补充一张 流程图 帮助大家更好理解!
如果这篇文章能对你起到一点帮助,那我倍感荣幸
如果有什么地方讲的不对 欢迎在评论中指出,我会加以改正万分感谢!