我有一个活动,在 3x4 矩阵中有 12 个图像视图。我想以编程方式将每个 ImageView 的图像和其他属性替换为不同的资源。我似乎找不到任何方法通过循环遍历视图,因此我必须对每个更改进行硬编码。我设法将 ImageViews 放入一个有帮助的数组中,但我希望有更好的方法。我查看了 KotlinX.Synthetic 和数据/视图绑定,但它们似乎没有帮助。 例如,要创建 ImageView 数组,我必须这样做:
var imgArray = arrayOf(findViewById<ImageView>(R.id.img01))
imgArray += findViewById<ImageView>(R.id.img02)
imgArray += findViewById<ImageView>(R.id.img03)
imgArray += findViewById<ImageView>(R.id.img04)
imgArray += findViewById<ImageView>(R.id.img05)
imgArray += findViewById<ImageView>(R.id.img06)
imgArray += findViewById<ImageView>(R.id.img07)
imgArray += findViewById<ImageView>(R.id.img08)
imgArray += findViewById<ImageView>(R.id.img09)
imgArray += findViewById<ImageView>(R.id.img10)
imgArray += findViewById<ImageView>(R.id.img11)
imgArray += findViewById<ImageView>(R.id.img12)
我希望做这样的事情:
var i = 1
for (listView in listViews) {
imgArray += findViewById<ImageView>("R.id.img" + i.tostring())
i++
}
但这行不通。 任何帮助将不胜感激。我有一些其他语言的经验,但对 kotlin/java/android 很陌生。
我通常走的路是
val imageViews = listOf(R.id.img1, R.id.img2, R.id.img3).map(findViewById(it))
这将在一行中构建视图列表。
或者,如果您真的不想使列表保持最新并且名称没有变化,那么获取给定名称的 idresources.getIdentifier("nameOfDrawable", "drawable", this.getPackageName())
。
我通常使用Gabe答案中的第一个示例,只是列出ID并使用它来创建可以迭代的有用集合。但根据情况,这里有几个其他选项可能更合适:
查找给定类型的所有视图
container.children.filterIsInstance<ImageView>()
这需要对ViewGroup
(例如ConstraintLayout
、GridLayout
等)的引用,基本上提取出某种类型的所有View
。如果它们以某种容器布局进行组织,则很有用,如果所有内容都在同一级别(例如鼓励您这样做的ConstraintLayout
),并且您不想包含其他相同类型的View
,则不会很有用。
此外,这仅适用于容器的直接后代,即将其作为父级的东西。如果这些东西中的任何一个有自己的后代,它们不包括在内(不过请参阅下面的函数!
使用标签
标记是可以添加到View
的一些数据,在具有tag
属性的 XML 中,或在具有setTag
的代码中。您可以使用它来确定您想要的ImageView
,如果无法在层次结构中组织它们。(层次结构更好,因为一旦设置,就没有工作,也没有什么可忘记的 - 您只需将视图与其他视图放在一起即可。
有一个findViewWithTag
函数,但它只返回一个View
,当你有一个想要抓取的组时,这是不好的。因此,我们可以编写一个辅助函数来获取ViewGroup
的所有后代(而不仅仅是其直系子代):
fun ViewGroup.getAllDescendants(): Sequence<View> =
children + children.filterIsInstance<ViewGroup>().flatMap { it.getAllDescendants() }
(这很有用,因为它可以处理嵌套层次结构中的View
,因此如果您有一个容器,您需要的所有内容都在内部,但作为内部层次结构的一部分,它也可以帮助上述filterByInstance
方法。
现在,您可以使用它来获取层次结构中的每个View
,并筛选所需的标签
// start with the root view, e.g. 'view' or 'binding.root' - or any container
// you want to search inside
(view as ViewGroup).getAllDescendants()
// you don't necessarily need to do this one, but it's safer and casts for you
.filterIsInstance<ImageView>()
.filter { it.tag == "cool image" }
如果 ImageView 位于同一父布局上,则只需查询布局的子布局。
你会得到一个儿童名单。
迭代列表。
您不必在正手上知道有多少图像视图。