如何在Kotlin中通过字符串ID结合ActivityMainBinding循环绑定TextView并赋值?
解决View Binding中通过字符串ID获取TextView的问题
先帮你梳理下代码里的小问题,再搞定核心的视图绑定需求——你的数组填充逻辑其实有漏洞,会导致后续赋值根本不会执行,然后再来说怎么通过字符串ID找到对应的TextView。
第一步:修正二维数组的填充逻辑
你原来的数组初始化和填充方式有两个明显问题:
val rows = arrayOf<Array<Int>>()创建的是空数组,调用rows.set(row, ...)会直接抛出索引越界异常rows[row].plus(...)不会修改原数组,因为plus返回的是一个新数组,原数组完全不会被改变
我们可以用更简洁的方式初始化并填充数组:
// 直接创建4行2列的数组,每个元素随机生成1或2 val rows = Array(4) { Array(2) { (1..2).random() } }
第二步:绑定TextView并赋值
这里提供两种实现方案,更推荐第二种,因为类型安全且没有反射开销:
方案1:用反射快速实现
View Binding生成的类里,每个视图ID都会对应一个同名属性(比如txtRow1Column1对应binding.txtRow1Column1),我们可以通过Kotlin反射获取这个属性:
private fun startNewRound() { // 初始化并填充数据数组 val rows = Array(4) { Array(2) { (1..2).random() } } // 遍历数组赋值 for (rowIndex in rows.indices) { val columns = rows[rowIndex] for (colIndex in columns.indices) { val value = columns[colIndex] // 生成对应的视图ID字符串(注意视图ID是1开始,所以索引要+1) val viewId = "txtRow${rowIndex + 1}Column${colIndex + 1}" // 通过反射拿到binding里的TextView val textView = binding::class.memberProperties .first { it.name == viewId } .get(binding) as TextView // 设置对应文本 textView.text = if (value == 1) getString(R.string.strTrue) else getString(R.string.strFalse) } } }
方案2:提前构建TextView二维数组(更推荐)
直接把所有TextView按行和列整理成二维数组,不用处理字符串ID,编译期就能检查视图是否存在,性能和可读性都更好:
private fun startNewRound() { // 把TextView按行和列组织成二维数组 val textViews = arrayOf( arrayOf(binding.txtRow1Column1, binding.txtRow1Column2), arrayOf(binding.txtRow2Column1, binding.txtRow2Column2), arrayOf(binding.txtRow3Column1, binding.txtRow3Column2), arrayOf(binding.txtRow4Column1, binding.txtRow4Column2) ) // 初始化数据数组 val rows = Array(4) { Array(2) { (1..2).random() } } // 遍历赋值 for (rowIndex in rows.indices) { for (colIndex in rows[rowIndex].indices) { val value = rows[rowIndex][colIndex] textViews[rowIndex][colIndex].text = if (value == 1) getString(R.string.strTrue) else getString(R.string.strFalse) } } }
小提示
建议尽量用0-based索引(从0开始)处理数组和视图索引,逻辑会更统一,减少混淆。方案2是生产环境里更稳妥的选择,毕竟反射不仅有性能损耗,还可能因为混淆等问题出意外。
内容的提问来源于stack exchange,提问作者A. Vreeswijk
相关产品推荐
相关产品推荐

