Android中动态设置资源id,通过反射以字符串"R.layout.xxx"设置资源

一些不常见的场景,获取到的资源是服务端下发字符串 "R.layout.sleep_activity","R.anim.fly_up"形式。
或者写Demo的时候,一个Activity对应多个布局,希望以外部传入字符串形式设置 setContentView(layout)。比如以下:

无标题.png

传递给目标Activity一个字符串“R.layout.xxx”,而本地对应的布局xxx有多个,需要加载到同一个目标Activity
方法之一是通过反射,从R资源类获取想要的“R.layout.xxx” 的int值,再setContentView(it)

/**
     *  应用:
     *  val layoutIdInt = Util.getIdByName(context, "layout", "R.layout.sleep_activity")
     * */
fun getIdByName(context: Context, typeName: String, name: String): Int {
        val packageName = context.packageName
        var id = 0
        try {
            val r = Class.forName("$packageName.R")
            val resTypes = r.classes
            var dstClass: Class<*>? = null

            // Search if has type we need?
            for (i in resTypes.indices) {

                // resTypes[i] is the type of resource, eg. "com.jesen.cod.layoutadvanced.R$anim"
                // end is typeName, eg. "anim"
                val end = resTypes[i].name.split("\\$").toTypedArray()[1]
                if (end == typeName) {
                    dstClass = resTypes[i]
                    break
                }
            }

            // Yes, find the type
            if (dstClass != null) {
                val simpleName = name.split("\\.").toTypedArray()[2]
                val f = dstClass.getField(simpleName)

                //f.setAccessible(true);
                Log.d("XXX", "getIdByName, f : $f")
                id = f.getInt(dstClass)
            }
        } catch (e: ClassNotFoundException) {
            e.printStackTrace()
        } catch (e: IllegalArgumentException) {
            e.printStackTrace()
        } catch (e: SecurityException) {
            e.printStackTrace()
        } catch (e: IllegalAccessException) {
            e.printStackTrace()
        } catch (e: NoSuchFieldException) {
            e.printStackTrace()
        }
        return id
    }

你可能感兴趣的:(Android中动态设置资源id,通过反射以字符串"R.layout.xxx"设置资源)