修改控件ID后使用ConstraintSet动态添加Barrier失效怎么解决?
问题根源
- 你手动硬编码的ID(1、2、3)属于Android系统保留的ID范围,ConstraintSet在解析约束时会将这类小数值ID误认为系统特殊ID(比如Parent ID),导致Barrier无法正确关联到textView1,约束规则失效。
- 你测试
View.generateViewId()时仅修改了textView1的ID,textView2和Barrier仍使用硬编码的小数值ID,依然存在ID冲突问题。
解决方法
所有动态设置的View ID都通过View.generateViewId()生成,不要使用硬编码的小数值ID,生成的ID符合Android规范,不会和系统保留ID、APP资源ID冲突,ConstraintSet就能正确识别各个View的身份。
修改后完整代码
package com.example.test_application; import android.os.Build; import android.os.Bundle; import android.view.View; import android.widget.TextView; import androidx.annotation.RequiresApi; import androidx.appcompat.app.AppCompatActivity; import androidx.constraintlayout.widget.Barrier; import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.ConstraintSet; public class MainActivity extends AppCompatActivity { @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1) @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ConstraintLayout myConstraintLayout = findViewById(R.id.content); View textView1 = findViewById(R.id.textView1); // 全部通过generateViewId生成合法ID,避免冲突 int text1NewId = View.generateViewId(); int text2Id = View.generateViewId(); int barrierId = View.generateViewId(); textView1.setId(text1NewId); TextView textView2 = new TextView(this); textView2.setId(text2Id); textView2.setText("HELLO"); myConstraintLayout.addView(textView2); ConstraintSet constraintSet = new ConstraintSet(); constraintSet.clone(myConstraintLayout); int[] barrierReferIds = {text1NewId}; constraintSet.createBarrier(barrierId, Barrier.END, 0, barrierReferIds); constraintSet.connect(text2Id, ConstraintSet.START, barrierId, ConstraintSet.END,0); constraintSet.connect(text2Id, ConstraintSet.TOP, text1NewId, ConstraintSet.TOP,0); constraintSet.applyTo(myConstraintLayout); } }
兼容低版本说明
如果你的应用minSdk低于17(Android 4.2),可以自行实现ID生成方法替代系统的View.generateViewId():
private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1); public static int generateViewId() { for (;;) { final int result = sNextGeneratedId.get(); int newValue = result + 1; if (newValue > 0x00FFFFFF) newValue = 1; if (sNextGeneratedId.compareAndSet(result, newValue)) { return result; } } }
内容的提问来源于stack exchange,提问作者user44644
相关产品推荐
相关产品推荐

