为什么我的 setOnClickListener 只适用于每次循环通过的最后一个元素?

Why does my setOnClickListener only apply to last element each loop pass?

抱歉,如果代码有点令人费解,多年来我一直在发垃圾邮件试图解决这个问题。

我在布局中创建子项并跟踪添加它们的数量,然后比较它们以便我们知道哪些集合属于哪些练习。单击箭头时,设置信息应该会折叠,但只有每个练习的最后一个视图会折叠。

fully loaded

clicking to hide

all buttons clicked to hide

    fun listeners() {
for (i in childCount3) {
    val imageButton: TextView = binding.parentLinearLayout.getChildAt(i).weightTxt
    val fragment = EditSetFragment()
    imageButton.setOnClickListener {
        supportFragmentManager.beginTransaction().replace(R.id.parent_linear_layout, fragment).commit()
    }
}
// childList = 10 | childList2 = [0,3,6,8] | childList3 = [1,2,4,5,7,9]
var testCount = 0
var testCount2 = 0
for (i in 0 until childCount2.size) {
    var matches = ArrayList<Int>()
    val imageButton: ImageButton = binding.parentLinearLayout.getChildAt(childCount2[i]).expandCard
    Log.d("I  ", i.toString())
    for (k in 0 until childCount3.size) {
        Log.d("k  ", k.toString())
        Log.d("CHECKER  ", binding.parentLinearLayout.getChildAt(childCount2[i]).instanceTxtEx.text.toString() + binding.parentLinearLayout.getChildAt(childCount3[k]).instanceTxt.text).toString()
        if(binding.parentLinearLayout.getChildAt(childCount2[i]).instanceTxtEx.text == binding.parentLinearLayout.getChildAt(childCount3[k]).instanceTxt.text) {
            matches.add(childCount3[k])
            Log.d("MATCH  ", i.toString())
            imageButton.setOnClickListener{
                binding.parentLinearLayout.getChildAt(childCount3[k]).visibility = GONE
            }

        }   
    }
}
}

有点难以理解你在做什么,但我认为你正在浏览 childCount2 中的每个项目,抓住它的展开按钮,然后尝试为每个 child 该项目在 childCount3?

问题是您只能在 View 上设置一个点击侦听器,因此在您的循环中您没有添加多个侦听器,每个侦听器都隐藏一个按钮,您每次都在替换当前侦听器。所以它最终只隐藏了您为其设置侦听器的最后一项。

如果您以编程方式将这些项目添加到布局中,难道您不能只存储每个 top-level 项目的 children 列表吗?这样你就可以为每个按钮设置一次监听器,并在其中引用你的 children 列表。像这样:

val parentsAndChildren = mutableMapOf<View, MutableList<View>>()

// Add your top-level (childCount2) views here, mapped to an empty list
// As you add children (childCount3), grab their parent's list and add the child to it

fun setUpCollapseButtons() {
    // iterate over all the parents and set a click listener on their buttons
    parentsAndChildren.keys.forEach { parent ->
        parent.expandCard.setOnClickListener {
            // grab the current list of children for this parent, and do the thing
            parentsAndChildren[parent].forEach { it.visibility = GONE }
            // could also do { it.visibility = if (it.visibility == VISIBLE) GONE else VISIBLE } for a toggle
        }
    }
}

我不是 100% 确定当 getChildAt 只是 returns 一个 View 时,您是如何引用 expandCard 之类的东西的,但是您可以使用 findViewById 在每个 parent 上设置点击侦听器时。希望这能给您带来灵感 - 只需跟踪视图本身就容易得多,而不必去挖掘它们(并进行文本比较以匹配它们)


如果您仍然想这样做,可以按照以下方法为每个设置一个点击侦听器:

// collect all the parent Views
val parents = childCount2.map { i -> binding.parentLinearLayout.getChildAt(i) }
parents.forEach { parent ->
    // collect all its children
    val children = childCount3.map { j -> binding.parentLinearLayout.getChildAt(j) }
        .filter { child -> parent.instanceTxtEx.text == child.instanceTxtEx.text  }

    // add a single click listener to the parent, make it affect all the children
    parent.expandCard.setOnClickListener {
        children.forEach { it.visibility = GONE }
    }
}

有更奇特的方法来收集 parents 和 children,但希望这是有意义的 - 您需要先收集它们,然后才能设置影响它们的点击监听器