Android开发中获取目标View或者所有View

133 阅读1分钟

有时候有些View是第三方的或者其他sdk的,显示在我们自己应用界面上,拿不到对象,这时可以通过如下方法。

/**
 * 获取界面中的所有View
 */

private fun hookView() {
    Handler().post {
        val wmGlobalClass = Class.forName("android.view.WindowManagerGlobal")
        //获取mView字段
        val viewsField = wmGlobalClass.getDeclaredField("mViews")
        viewsField?.isAccessible = true
        //获取getInstance方法
        val getInstanceMethod = wmGlobalClass.getDeclaredMethod("getInstance")
        //调用getInstance方法获取Window
        val wmGlobalInstance = getInstanceMethod.invoke(null)
        //获取当前屏幕上的View列表
        val views = viewsField.get(wmGlobalInstance) as? ArrayList<View>
        val size = views?.size ?: 0
        for (i in 0..size) {
            // 假设某个条件满足时退出循环
            val targetView = getTargetView(getDecorView(views?.get(i))) ?: break
            Log.d("tanyl", "targetView =$targetView")
        }
    }
}

第二种就是需要获取界面的某个View,我们可以抓布局知道id。

/**
 * 从View列表里面中获取DecorView
 */
private fun getDecorView(view: View?): View? {
    if (view == null) {
        return null
    }
    if (view.javaClass.simpleName.startsWith("DecorView")) {
        return view
    }
    return null
}

/**
 * 获取目标View targetView
 */
private fun getTargetView(view: View?): View? {
    val targetView = view?.findViewById<View>(R.id.button)
    if (targetView?.id == R.id.button) {
        return targetView
    }
    return null
}

运行结果:

image.png