前言

事件分发是一个困扰我已久的问题,今天终于鼓起勇气手撸代码来一探究竟,废话不多说,直接上代码。

首先,先粘出今天学习需要创建的类,Activity  =>  ViewGroup  =>  View

还是上代码吧

1.Activity

class DispatchEventActivity : AppCompatActivity(){    private val TAG: String = "study_DisActivity"    override fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        setContentView(R.layout.activity_dispatchevent)           }    override fun dispatchTouchEvent(event: MotionEvent): Boolean {        when (event.action) {            MotionEvent.ACTION_DOWN -> {                Log.d(TAG, "Activity dispatchTouchEvent ACTION_DOWN")            }            MotionEvent.ACTION_MOVE -> {                Log.d(TAG, "Activity dispatchTouchEvent ACTION_MOVE")            }            MotionEvent.ACTION_UP -> {                Log.d(TAG, "Activity dispatchTouchEvent ACTION_UP")            }        }        return super.dispatchTouchEvent(event)    }    override fun onTouchEvent(event: MotionEvent): Boolean {        when (event.action) {            MotionEvent.ACTION_DOWN -> {                Log.d(TAG, "Activity onTouchEvent ACTION_DOWN")            }            MotionEvent.ACTION_MOVE -> {                Log.d(TAG, "Activity onTouchEvent ACTION_MOVE")            }            MotionEvent.ACTION_UP -> {                Log.d(TAG, "Activity onTouchEvent ACTION_UP")            }        }        return super.onTouchEvent(event)    }}

2.View

class MyTextView @JvmOverloads constructor(        context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : TextView(context, attrs, defStyleAttr) {    private val TAG: String = "study_My TextView"    override fun dispatchTouchEvent(event: MotionEvent): Boolean {        when (event.action) {            MotionEvent.ACTION_DOWN -> {                Log.d(TAG, "View dispatchTouchEvent ACTION_DOWN")            }            MotionEvent.ACTION_MOVE -> {                Log.d(TAG, "View dispatchTouchEvent ACTION_MOVE")            }            MotionEvent.ACTION_UP -> {                Log.d(TAG, "View dispatchTouchEvent ACTION_UP")            }        }        return super.dispatchTouchEvent(event)    }    override fun onTouchEvent(event: MotionEvent): Boolean {        when (event.action) {            MotionEvent.ACTION_DOWN -> {                Log.d(TAG, "View onTouchEvent ACTION_DOWN")            }            MotionEvent.ACTION_MOVE -> {                Log.d(TAG, "View onTouchEvent ACTION_MOVE")            }            MotionEvent.ACTION_UP -> {                Log.d(TAG, "View onTouchEvent ACTION_UP")            }        }        return super.onTouchEvent(event)    }}

3.ViewGroup

class MyLinearLayout @JvmOverloads constructor(        context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : LinearLayout(context, attrs, defStyleAttr) {    private val TAG: String = "study_ LinLayout"    override fun onInterceptTouchEvent(event: MotionEvent): Boolean {        when (event.action) {            MotionEvent.ACTION_DOWN -> {                Log.d(TAG, "ViewGroup onInterceptTouchEvent ACTION_DOWN")            }            MotionEvent.ACTION_MOVE -> {                Log.d(TAG, "ViewGroup onInterceptTouchEvent ACTION_MOVE")            }            MotionEvent.ACTION_UP -> {                Log.d(TAG, "ViewGroup onInterceptTouchEvent ACTION_UP")            }        }        return super.onInterceptTouchEvent(event)    }    override fun dispatchTouchEvent(event: MotionEvent): Boolean {        when (event.action) {            MotionEvent.ACTION_DOWN -> {                Log.d(TAG, "ViewGroup dispatchTouchEvent ACTION_DOWN")            }            MotionEvent.ACTION_MOVE -> {                Log.d(TAG, "ViewGroup dispatchTouchEvent ACTION_MOVE")            }            MotionEvent.ACTION_UP -> {                Log.d(TAG, "ViewGroup dispatchTouchEvent ACTION_UP")            }        }        return super.dispatchTouchEvent(event)    }    override fun onTouchEvent(event: MotionEvent): Boolean {        when (event.action) {            MotionEvent.ACTION_DOWN -> {                Log.d(TAG, "ViewGroup onTouchEvent ACTION_DOWN")            }            MotionEvent.ACTION_MOVE -> {                Log.d(TAG, "ViewGroup onTouchEvent ACTION_MOVE")            }            MotionEvent.ACTION_UP -> {                Log.d(TAG, "ViewGroup onTouchEvent ACTION_UP")            }        }        return super.onTouchEvent(event)    }}

接下来看一下布局文件吧,白色部分为MyLinearLayout,灰色部分为MyTextView

接下来我们运行我们的代码,并点击屏幕测试,打印Log如下:

07-31 11:23:51.908 20729-20729/? D/study_DisActivity: Activity dispatchTouchEvent ACTION_DOWN07-31 11:23:51.908 20729-20729/? D/study_  LinLayout: ViewGroup dispatchTouchEvent ACTION_DOWN07-31 11:23:51.908 20729-20729/? D/study_  LinLayout: ViewGroup onInterceptTouchEvent ACTION_DOWN07-31 11:23:51.909 20729-20729/? D/study_My TextView: View dispatchTouchEvent ACTION_DOWN07-31 11:23:51.909 20729-20729/? D/study_My TextView: View onTouchEvent ACTION_DOWN07-31 11:23:51.910 20729-20729/? D/study_  LinLayout: ViewGroup onTouchEvent ACTION_DOWN07-31 11:23:51.912 20729-20729/? D/study_DisActivity: Activity  onTouchEvent ACTION_DOWN07-31 11:23:51.940 20729-20729/? D/study_DisActivity: Activity dispatchTouchEvent ACTION_UP07-31 11:23:51.940 20729-20729/? D/study_DisActivity: Activity onTouchEvent ACTION_UP

从日志我们分析出

从ACTION_DOWN 事件我们可以看出来,事件的分发过程确实是以 “U”型进行传递的。当然这一切都归于没有任何“人”消费事件的情况下。

假如我们对View设置一个onTouch事件并返回false【不消费事件】,我们设置好事件后重新执行代码,日志如下:

07-31 11:47:32.243 22295-22295/? D/study_DisActivity: Activity dispatchTouchEvent ACTION_DOWN07-31 11:47:32.243 22295-22295/? D/study_  LinLayout: ViewGroup dispatchTouchEvent ACTION_DOWN07-31 11:47:32.244 22295-22295/? D/study_  LinLayout: ViewGroup onInterceptTouchEvent ACTION_DOWN07-31 11:47:32.244 22295-22295/? D/study_My TextView: View dispatchTouchEvent ACTION_DOWN07-31 11:47:32.244 22295-22295/? D/study_DisActivity: View onTouch ACTION_DOWN07-31 11:47:32.245 22295-22295/? D/study_My TextView: View onTouchEvent ACTION_DOWN07-31 11:47:32.245 22295-22295/? D/study_  LinLayout: ViewGroup onTouchEvent ACTION_DOWN07-31 11:47:32.247 22295-22295/? D/study_DisActivity: Activity onTouchEvent ACTION_DOWN07-31 11:47:32.286 22295-22295/? D/study_DisActivity: Activity dispatchTouchEvent ACTION_UP07-31 11:47:32.286 22295-22295/? D/study_DisActivity: Activity onTouchEvent ACTION_UP

这次我们看到onTouch 是优先于onTouchEvent 执行的,由此我们推测,如果onTouch返回true消费事件的话,那么View的onTouchEvent将不被执行,那么也就不会继续分发事件,接下来我们修改onTouch返回值为true,并查看日志:

07-31 11:52:03.698 22665-22665/? D/study_DisActivity: Activity dispatchTouchEvent ACTION_DOWN07-31 11:52:03.698 22665-22665/? D/study_  LinLayout: ViewGroup dispatchTouchEvent ACTION_DOWN07-31 11:52:03.698 22665-22665/? D/study_  LinLayout: ViewGroup onInterceptTouchEvent ACTION_DOWN07-31 11:52:03.698 22665-22665/? D/study_My TextView: View dispatchTouchEvent ACTION_DOWN07-31 11:52:03.699 22665-22665/? D/study_DisActivity: View onTouch ACTION_DOWN07-31 11:52:03.738 22665-22665/? D/study_DisActivity: Activity dispatchTouchEvent ACTION_UP07-31 11:52:03.739 22665-22665/? D/study_  LinLayout: ViewGroup dispatchTouchEvent ACTION_UP07-31 11:52:03.739 22665-22665/? D/study_  LinLayout: ViewGroup onInterceptTouchEvent ACTION_UP07-31 11:52:03.739 22665-22665/? D/study_My TextView: View dispatchTouchEvent ACTION_UP07-31 11:52:03.739 22665-22665/? D/study_DisActivity: View onTouch ACTION_UP

此处验证了我们的推测,ACTION_DOWN的事件到onTouch后被消费掉了,没有继续分发。我发现为何ACTION_UP事件如此奇怪,想了好久感觉可能是,当所有人都不消费事件时,就相当于处理权交给了Activity的onTouchEvent,所以ACTION_UP事件就分发到Activity的onTouchEvent结束,当我们把onTouch返回值改为true后,也就是onTouch要消费事件,那么ACTION_UP就会继续分发事件到onTouch里面。

如果View有onClick 事件会怎么样呢?我们还是修改代码看日志吧;

07-31 12:04:41.110 23525-23525/? D/study_DisActivity: Activity dispatchTouchEvent ACTION_DOWN07-31 12:04:41.110 23525-23525/? D/study_  LinLayout: ViewGroup dispatchTouchEvent ACTION_DOWN07-31 12:04:41.110 23525-23525/? D/study_  LinLayout: ViewGroup onInterceptTouchEvent ACTION_DOWN07-31 12:04:41.110 23525-23525/? D/study_My TextView: View dispatchTouchEvent ACTION_DOWN07-31 12:04:41.110 23525-23525/? D/study_DisActivity: View onTouch ACTION_DOWN07-31 12:04:41.111 23525-23525/? D/study_My TextView: View onTouchEvent ACTION_DOWN07-31 12:04:41.142 23525-23525/? D/study_DisActivity: Activity dispatchTouchEvent ACTION_UP07-31 12:04:41.142 23525-23525/? D/study_  LinLayout: ViewGroup dispatchTouchEvent ACTION_UP07-31 12:04:41.142 23525-23525/? D/study_  LinLayout: ViewGroup onInterceptTouchEvent ACTION_UP07-31 12:04:41.142 23525-23525/? D/study_My TextView: View dispatchTouchEvent ACTION_UP07-31 12:04:41.142 23525-23525/? D/study_DisActivity: View onTouch ACTION_UP07-31 12:04:41.142 23525-23525/? D/study_My TextView: View onTouchEvent ACTION_UP07-31 12:04:41.143 23525-23525/? D/study_DisActivity:  View onClick

我们发现如果View有onClick 方法,那么事件最终会被onClick 消费掉。

到此我们已经大致摸清了事件传递的过程,今天的学习就先到这里,有疑问的同学可以回复评论,咱们一起讨论学习,在此过程中提高我们自己。

更多相关文章

  1. [置顶] android中屏幕触摸事件
  2. android_8.1 hdmi设备热插拔事件
  3. Android之屏幕方向改变以及onConfigurationChanged事件
  4. Android7 InputReader InputDispatcher Key Touch
  5. Android(安卓)ListView setOnItemClickListener/setOnItemSelect
  6. Android(安卓)连续多次点击事件的实现
  7. android中view手势滑动冲突的解决方法
  8. Android(安卓)笔记5---事件处理和手势
  9. Android之广播大全 Intent Action 事件

随机推荐

  1. 《游戏程序设计模式》 2.2 - 游戏循环
  2. 网页游戏用的什么编程语言
  3. MySql基础语法的学习-基础的查询语句
  4. SpringBoot+Vue3前后端分离,实战wiki知识
  5. 态路小课堂丨QSFP-DD封装模式光模块接口
  6. 前端inline元素间隙问题解决办法
  7. 游戏云间之五:游戏架构
  8. MyBatis的SQL执行流程,逻辑超清晰,总结得也
  9. TaskBuilder低代码开发平台怎么样?
  10. Linux常用命令的超全整理(附Linux学习笔记