如何移除代码动态创建的TextView?ConstraintLayout下清除无效问题
解决ConstraintLayout旧视图未移除的问题
你当前代码里用ConstraintSet.clear(v.id)只是清除了视图的约束关系,并没有从父布局中移除视图本身,所以旧视图会一直留在屏幕上,新视图叠加上去就会出现覆盖的情况。
正确的做法是直接从父布局中移除所有旧子视图,替换掉原来的约束清除逻辑:
private fun generateView(tirage:CharArray) { val set = ConstraintSet() val parentLayout = binding.reglette var i = 0 // 替换原来的ConstraintSet.clear逻辑:直接移除所有子视图 for (v in parentLayout.children.toList()) { // 转成List避免遍历中修改集合的问题 parentLayout.removeView(v) } listLettre.clear() // 以下原有逻辑保持不变 val dummyLeft = TextView(requireActivity()) listLettre.add(dummyLeft) listPos.add(i) listIndex.add(i++) for (lettre in tirage) { val childView = TextView(requireActivity()) childView.id = View.generateViewId() childView.width = LARGEUR_LETTRE.toInt() childView.height = LARGEUR_LETTRE.toInt() childView.setBackgroundResource(R.drawable.lettre) childView.gravity = Gravity.CENTER childView.text = lettre.toString() childView.textSize = 34f childView.setTypeface(null, Typeface.BOLD) parentLayout.addView(childView, i - 1) listLettre.add(childView) listPos.add(i) listIndex.add(i++) } val dummyRight = TextView(requireActivity()) listLettre.add(dummyRight) listPos.add(i) listIndex.add(i) val premL = listLettre.drop(1).first() val pad = (parentLayout.width - (tirage.size * LARGEUR_LETTRE.toInt())) / 2 set.clone(parentLayout) set.connect( premL.id, ConstraintSet.START, ConstraintSet.PARENT_ID, ConstraintSet.START, pad ) val windowedList = listLettre.drop(1).dropLast(1).windowed(2, 1, false) for (pair in windowedList) set.connect( pair.last().id, ConstraintSet.START, pair.first().id, ConstraintSet.END ) set.applyTo(parentLayout) }
补充说明
- 遍历子视图时要转成
toList(),因为直接遍历parentLayout.children(这是一个动态集合)时,移除元素会导致集合结构变化,引发遍历异常。 - 如果你的
listLettre里保存的是之前的旧视图,调用listLettre.clear()已经能清空列表,但关键还是要从父布局中移除视图实体,否则它们会一直占据布局空间。
内容的提问来源于stack exchange,提问作者Simon W
相关产品推荐
相关产品推荐

