通过反射获取view再layout里面设置的onclick属性值

本文介绍了一种通过反射机制获取Android中View组件在res/Layout布局文件中声明的onClick属性名称的方法。此方法适用于直接在XML布局文件中定义的点击事件,但不包括通过DataBinding方式设置的监听器。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

   /**
         * 通过反射,获取View的在res/Layout布局中声明的onClick属性名称
         * 但是通过databinding方式设置的值获取不到
         * 
         */
        fun getViewClickListenerName(view: View?): String? {
            var clickName: String? = null
            try {
                // get the nested class `android.view.View$ListenerInfo`
                val listenerInfoField: Field? = View::class.java.getDeclaredField("mListenerInfo")
                listenerInfoField?.isAccessible = true
                val myViewListenerInfo = listenerInfoField?.get(view)

                // get the field mOnClickListener, that holds the listener and cast it to a listener
                val onClickListener: Field? =
                    myViewListenerInfo?.javaClass?.getDeclaredField("mOnClickListener")
                onClickListener?.isAccessible = true
                val myClickListener = onClickListener?.get(myViewListenerInfo)

                val fields = myClickListener?.javaClass?.declaredFields
                fields?.apply {
                    for (field in fields) {
                        if (field.name.equals("mMethodName")) {
                            //get the field mMethodName
                            val mMethodName: Field? =
                                myClickListener.javaClass.getDeclaredField("mMethodName")
                            mMethodName?.isAccessible = true
                            //get my MethodName
                            val myMethodName = mMethodName?.get(myClickListener)
                            clickName = myMethodName as String?
                        }
                    }
                }

            } catch (e: ClassNotFoundException) {
                e.printStackTrace()
            } catch (e: IllegalAccessException) {
                e.printStackTrace()
            } catch (e: Exception) {
                e.printStackTrace()
            }
            return clickName
        }

 

 

同上一个方法:

  /**
         * 通过反射,获取View的在res/Layout布局中声明的onClick属性名称
         *
         */
        private fun getOnClickName(view: View?): String {
            if (view == null) {
                throw NullPointerException("view == null")
            }
            var Name = ""

            // 反射 View.mListenerInfo.mOnClickListener.val$handlerName
            try {
                val mListenerInfo = getSubField(view, "mListenerInfo")
                val mOnClickListener = getSubField(mListenerInfo, "mOnClickListener")
                val handlerName = getSubField(mOnClickListener, "mMethodName")
                Name = handlerName as String
            } catch (e: Exception) {
                e.printStackTrace()
            }
            return Name
        }


        /**
         * 反射获取obj的成员变量fieldName(成员变量名获取,可在调试时动态查看)
         */
        private fun getSubField(obj: Any?, fieldName: String): Any? {
            if (obj == null) {
                throw NullPointerException("obj == null")
            }

            var subObj: Any? = null
            try {
                val field: Field? = obj.javaClass.getDeclaredField(fieldName)    // 获取成员变量对应的Field方法
                field?.isAccessible = true    // 设置为可访问
                subObj = field?.get(obj)    // 通过Field方法从Object中提取子变量
            } catch (ex: Exception) {
                ex.printStackTrace()
            }

            return subObj
        }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值