如何编程在ConstraintLayout中动态设置CheckBox实现每行两列布局
问题原因
动态向ConstraintLayout添加子View时未配置布局约束,所有无约束的子View会默认堆叠在布局左上角,因此出现CheckBox重叠的现象。不需要替换布局类型,只要在添加控件时为每个CheckBox设置对应ConstraintLayout.LayoutParams约束,即可实现每行2列的排列效果。
实现代码
首先准备dp转px的工具方法,避免直接使用px值导致不同分辨率设备显示异常:
// dp单位转px单位工具方法 private int dp2px(int dpVal) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpVal, getResources().getDisplayMetrics()); }
在原有逻辑基础上修改控件添加部分的代码,间距参数可以根据UI需求自行调整:
linearMain = findViewById(R.id.clReasons); int itemTotal = reasonsList.size(); // 间距配置,单位dp final int HORIZONTAL_MARGIN = dp2px(5); final int VERTICAL_MARGIN = dp2px(8); final int COLUMN_GAP = dp2px(10); // 记录上一行左列CheckBox的ID,用于设置下一行的顶部约束 int lastLeftViewId = ConstraintLayout.LayoutParams.PARENT_ID; for (int index = 0; index < itemTotal; index++) { CheckBox checkBox = new CheckBox(OrderStatus.this); int viewId = Integer.parseInt(reasonsList.get(index).get(ReasonInfo.ReasonID)); checkBox.setId(viewId); checkBox.setText(reasonsList.get(index).get(ReasonInfo.ReasonDesc)); // 初始化布局参数:宽度为MATCH_CONSTRAINT(0dp),高度包裹内容 ConstraintLayout.LayoutParams params = new ConstraintLayout.LayoutParams( 0, ConstraintLayout.LayoutParams.WRAP_CONTENT ); // 两列等宽分配 params.horizontalWeight = 1f; if (index % 2 == 0) { // 左列控件约束 params.leftToLeft = ConstraintLayout.LayoutParams.PARENT_ID; params.rightToRight = ConstraintLayout.LayoutParams.PARENT_ID; params.leftMargin = HORIZONTAL_MARGIN; params.rightMargin = COLUMN_GAP / 2; // 顶部约束:第一行对齐父布局顶部,后续行对齐上一行左列控件底部 if (index == 0) { params.topToTop = ConstraintLayout.LayoutParams.PARENT_ID; params.topMargin = VERTICAL_MARGIN; } else { params.topToBottom = lastLeftViewId; params.topMargin = VERTICAL_MARGIN; } lastLeftViewId = viewId; } else { // 右列控件约束 params.leftToLeft = ConstraintLayout.LayoutParams.PARENT_ID; params.rightToRight = ConstraintLayout.LayoutParams.PARENT_ID; params.leftMargin = COLUMN_GAP / 2; params.rightMargin = HORIZONTAL_MARGIN; // 顶部和同排左列控件对齐 params.topToTop = lastLeftViewId; } // 最后一行控件添加底部约束,保证父布局wrap_content高度计算正确 if (index == itemTotal - 1) { params.bottomToBottom = ConstraintLayout.LayoutParams.PARENT_ID; params.bottomMargin = VERTICAL_MARGIN; } checkBox.setLayoutParams(params); linearMain.addView(checkBox); }
注意事项
- 原有order.xml中的
clReasons布局不需要做任何修改,可以直接复用 - 不要给CheckBox设置固定宽度,通过
0dp + horizontalWeight=1f的方式可以保证两列在所有屏幕尺寸下都等宽展示 - 最后一行的控件必须设置底部约束到父布局,否则
ConstraintLayout的wrap_content模式无法正确计算总高度,会出现内容截断的问题 - 所有间距参数可以根据实际设计需求调整数值,不要直接写硬编码的px值
内容的提问来源于stack exchange,提问作者Rajkiranpandi M
相关产品推荐
相关产品推荐

