Android — 手撸代码学习事件分发的过程

前言

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

首先,先粘出今天学习需要创建的类,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_DOWN


07-31 11:23:51.908 20729-20729/? D/study_  LinLayout: ViewGroup dispatchTouchEvent ACTION_DOWN
07-31 11:23:51.908 20729-20729/? D/study_  LinLayout: ViewGroup onInterceptTouchEvent ACTION_DOWN


07-31 11:23:51.909 20729-20729/? D/study_My TextView: View dispatchTouchEvent ACTION_DOWN
07-31 11:23:51.909 20729-20729/? D/study_My TextView: View onTouchEvent ACTION_DOWN


07-31 11:23:51.910 20729-20729/? D/study_  LinLayout: ViewGroup onTouchEvent ACTION_DOWN


07-31 11:23:51.912 20729-20729/? D/study_DisActivity: Activity  onTouchEvent ACTION_DOWN


07-31 11:23:51.940 20729-20729/? D/study_DisActivity: Activity dispatchTouchEvent ACTION_UP
07-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_DOWN

07-31 11:47:32.243 22295-22295/? D/study_  LinLayout: ViewGroup dispatchTouchEvent ACTION_DOWN
07-31 11:47:32.244 22295-22295/? D/study_  LinLayout: ViewGroup onInterceptTouchEvent ACTION_DOWN

07-31 11:47:32.244 22295-22295/? D/study_My TextView: View dispatchTouchEvent ACTION_DOWN
07-31 11:47:32.244 22295-22295/? D/study_DisActivity: View onTouch ACTION_DOWN
07-31 11:47:32.245 22295-22295/? D/study_My TextView: View onTouchEvent ACTION_DOWN

07-31 11:47:32.245 22295-22295/? D/study_  LinLayout: ViewGroup onTouchEvent ACTION_DOWN
07-31 11:47:32.247 22295-22295/? D/study_DisActivity: Activity onTouchEvent ACTION_DOWN
07-31 11:47:32.286 22295-22295/? D/study_DisActivity: Activity dispatchTouchEvent ACTION_UP
07-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_DOWN
07-31 11:52:03.698 22665-22665/? D/study_  LinLayout: ViewGroup dispatchTouchEvent ACTION_DOWN
07-31 11:52:03.698 22665-22665/? D/study_  LinLayout: ViewGroup onInterceptTouchEvent ACTION_DOWN
07-31 11:52:03.698 22665-22665/? D/study_My TextView: View dispatchTouchEvent ACTION_DOWN
07-31 11:52:03.699 22665-22665/? D/study_DisActivity: View onTouch ACTION_DOWN


07-31 11:52:03.738 22665-22665/? D/study_DisActivity: Activity dispatchTouchEvent ACTION_UP
07-31 11:52:03.739 22665-22665/? D/study_  LinLayout: ViewGroup dispatchTouchEvent ACTION_UP
07-31 11:52:03.739 22665-22665/? D/study_  LinLayout: ViewGroup onInterceptTouchEvent ACTION_UP
07-31 11:52:03.739 22665-22665/? D/study_My TextView: View dispatchTouchEvent ACTION_UP
07-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_DOWN
07-31 12:04:41.110 23525-23525/? D/study_  LinLayout: ViewGroup dispatchTouchEvent ACTION_DOWN
07-31 12:04:41.110 23525-23525/? D/study_  LinLayout: ViewGroup onInterceptTouchEvent ACTION_DOWN
07-31 12:04:41.110 23525-23525/? D/study_My TextView: View dispatchTouchEvent ACTION_DOWN
07-31 12:04:41.110 23525-23525/? D/study_DisActivity: View onTouch ACTION_DOWN
07-31 12:04:41.111 23525-23525/? D/study_My TextView: View onTouchEvent ACTION_DOWN
07-31 12:04:41.142 23525-23525/? D/study_DisActivity: Activity dispatchTouchEvent ACTION_UP
07-31 12:04:41.142 23525-23525/? D/study_  LinLayout: ViewGroup dispatchTouchEvent ACTION_UP
07-31 12:04:41.142 23525-23525/? D/study_  LinLayout: ViewGroup onInterceptTouchEvent ACTION_UP
07-31 12:04:41.142 23525-23525/? D/study_My TextView: View dispatchTouchEvent ACTION_UP
07-31 12:04:41.142 23525-23525/? D/study_DisActivity: View onTouch ACTION_UP
07-31 12:04:41.142 23525-23525/? D/study_My TextView: View onTouchEvent ACTION_UP

07-31 12:04:41.143 23525-23525/? D/study_DisActivity:  View onClick

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值