探究 | 如何捕获一个 Activity页面上所有的点击行为

前言

最近逛wanAndroid论坛,发现一个有趣的问题:如何捕获一个Activity页面上所有的点击行为

一起研究下吧,不想看源码的小伙伴可以直接看文末总结~

准备工作

先得罗列出页面上的一些点击行为,常用的有:

  • 普通View的点击
  • 动态add的View的点击
  • Dialog上的按钮点击

于是就有了如下代码:


class MainActivity : AppCompatActivity() {
   

    override fun onCreate(savedInstanceState: Bundle?) {
   
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        btn1.setOnClickListener {
   
            showToast("点了按钮1")
        }


        btn2.setOnClickListener {
   
            val builder =
                AlertDialog.Builder(this)
                    .setTitle("我是一个dialog")
            val view: View = layoutInflater.inflate(R.layout.dialog_btn, null)
            val btn4 =
                view.findViewById<View>(R.id.btn4)
            btn4.setOnClickListener {
   
                showToast("点击了Dialog按钮")
            }
            builder.setView(view)
            builder.create().show()
        }


        btn3.setOnClickListener {
   

            var button = Button(this)
            button.text = "我是新加的按钮"
            var param = LinearLayout.LayoutParams(
                ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT
            )
            mainlayout.addView(button, param)

            button.setOnClickListener {
   
                showToast("点击了新加的按钮")
            }
        }
    }
}

既然我要捕获点击事件,首先就想到的是通过事件分发机制,也就是在源头就去获取所有的触摸事件,然后对点击事件进行统计,干吧~

事件分发

重写Activity的dispatchTouchEvent方法,由于只有点击事件,所以只需要统计ACTION_UP事件即可,如果有长按事件就在需要判断下按下的时间。


    override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
   
        ev?.let {
   
            when (ev.action) {
   
                MotionEvent.ACTION_UP -> {
   
                    Log.e(Companion.TAG,"ACTION_UP——CLICK") 
                }
                else -> {
   }
            }
        }
        return super.dispatchTouchEvent(ev)
    }

ok,运行下。

  • 点击按钮1,日志打印正常
  • 点击按钮2中的dialog按钮,日志。。。没有
  • 点击按钮3中的button,日志打印正常

结果大家也看到了,Dialog中的点击事件无法被响应,这是为啥呢?

这就要从事件分发机制说起了,点击屏幕首先响应的是当前屏幕的顶层View,也就是DecorView,在Activity中也就是Window的根布局。然后DecorView会调用Activity的dispatchTouchEvent方法,作为开发者事件分发的一个控制拦截,最后重新返回到DecorViewsuper.dispatchTouchEvent(event)方法开始ViewGroup的事件传递。看看相关源码:


//DecorView.java
    @Override
    public boolean dispatchTouchEvent
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值