如何修复通过代码在ConstraintLayout中创建指定TextView布局时的位置异常问题
解决ConstraintSet编程布局TextView显示在左上角的问题
你遇到的问题主要有三个核心点没处理到位:没有给TextView设置宽高约束、没有将ConstraintSet的配置应用到布局上,还有中间两个TextView缺少水平平分宽度的权重设置。调整这几点后就能实现和XML一致的布局效果了:
具体修改要点
- 给每个TextView设置宽高为0dp:对应XML里的
android:layout_width="0dp"和android:layout_height="0dp",代码中需要通过LayoutParams明确设置 - 添加ConstraintSet的应用操作:配置完所有约束后,必须调用
cs.applyTo(layout)才能让约束生效 - 给中间两个TextView设置水平权重:让t2和t3平分父布局的宽度,还原XML中的平分效果
完整修改后的Kotlin代码
val layout = findViewById<ConstraintLayout>(R.id.main) val cs = ConstraintSet() cs.clone(layout) val textViews: MutableList<TextView> = ArrayList<TextView>() for (i in 1..4) { val t = TextView(this) t.id = View.generateViewId() t.text = "Text" + i.toString() // 设置宽高为0dp,对应XML的match_constraint val params = ConstraintLayout.LayoutParams( 0, 0 ) layout.addView(t, params) textViews.add(t) } val t1 = textViews[0] val t2 = textViews[1] val t3 = textViews[2] val t4 = textViews[3] // 配置t1的约束 cs.connect(t1.id, ConstraintSet.BOTTOM, t2.id, ConstraintSet.TOP) cs.connect(t1.id, ConstraintSet.END, layout.id, ConstraintSet.END) cs.connect(t1.id, ConstraintSet.START, layout.id, ConstraintSet.START) cs.connect(t1.id, ConstraintSet.TOP, layout.id, ConstraintSet.TOP) // 配置t2的约束,添加水平权重 cs.connect(t2.id, ConstraintSet.BOTTOM, t4.id, ConstraintSet.TOP) cs.connect(t2.id, ConstraintSet.END, t3.id, ConstraintSet.START) cs.connect(t2.id, ConstraintSet.START, layout.id, ConstraintSet.START) cs.connect(t2.id, ConstraintSet.TOP, t1.id, ConstraintSet.BOTTOM) cs.setHorizontalWeight(t2.id, 1f) // 配置t3的约束,添加水平权重 cs.connect(t3.id, ConstraintSet.BOTTOM, t4.id, ConstraintSet.TOP) cs.connect(t3.id, ConstraintSet.END, layout.id, ConstraintSet.END) cs.connect(t3.id, ConstraintSet.START, t2.id, ConstraintSet.END) cs.connect(t3.id, ConstraintSet.TOP, t1.id, ConstraintSet.BOTTOM) cs.setHorizontalWeight(t3.id, 1f) // 配置t4的约束 cs.connect(t4.id, ConstraintSet.BOTTOM, layout.id, ConstraintSet.BOTTOM) cs.connect(t4.id, ConstraintSet.END, layout.id, ConstraintSet.END) cs.connect(t4.id, ConstraintSet.START, layout.id, ConstraintSet.START) cs.connect(t4.id, ConstraintSet.TOP, t2.id, ConstraintSet.BOTTOM) // 关键:将约束应用到布局上 cs.applyTo(layout)
补充说明
- 设置宽高为0dp是因为我们依赖ConstraintLayout的约束来控制View的大小,这和XML中的
match_constraint效果完全一致 setHorizontalWeight方法让t2和t3在水平方向平分可用空间,完美还原XML中两个View互相约束且宽度为0dp的平分效果- 最后调用
cs.applyTo(layout)是核心步骤,你之前的代码就是漏掉了这一步,导致所有约束都未生效,View只能使用默认的wrap_content属性且无约束,所以全部堆在屏幕左上角
内容的提问来源于stack exchange,提问作者Loma Harshana
相关产品推荐
相关产品推荐

