HorizontalScrollView内TableLayout的setStretchAllColumns在Lollipop中失效
这是个很常见的Android版本兼容性坑,我之前也碰到过类似情况,主要原因是Lollipop(API 21)及更早版本中,TableLayout嵌套在HorizontalScrollView里时,系统的列拉伸机制(stretchColumns、setStretchAllColumns等)无法正常工作——因为HorizontalScrollView会让子View的宽度不受父容器宽度限制,早期系统的TableLayout无法正确计算这种场景下的列宽规则。
下面是两种快速解决的方案,你可以根据需求选择:
方案一:手动控制EditText宽度(最小改动)
这种方法不需要大幅修改现有代码,只需要去掉系统的拉伸规则,手动给每个EditText设置固定宽度,让TableLayout能正确计算总宽度,从而让HorizontalScrollView正常滚动。
步骤1:修改XML中的TableLayout属性
去掉android:stretchColumns="*",因为我们要手动控制宽度:
<TableLayout android:id="@+id/tbl" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="20dp" />
步骤2:修改MainActivity的generate方法
取消系统拉伸设置,给每个EditText添加明确的布局参数和固定宽度:
public void generate(View view) { tl.removeAllViews(); // 取消所有系统拉伸规则 tl.setStretchAllColumns(false); for (int j = 0; j < tl.getColumnCount(); j++) { tl.setColumnStretchable(j, false); } M = Integer.parseInt(edr.getText().toString()); // 定义每个EditText的宽度(这里用80dp转成px,你可以根据需求调整) int editTextWidth = (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, 80, getResources().getDisplayMetrics() ); for (int i = 0; i < M; i++) { TableRow tr = new TableRow(this); tr.setBackgroundColor(getResources().getColor(R.color.cold)); // 给TableRow设置布局参数 tr.setLayoutParams(new TableRow.LayoutParams( TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT )); for (int j = 0; j < M; j++) { EditText ed = new EditText(this); // 设置固定宽度和布局参数 TableRow.LayoutParams editParams = new TableRow.LayoutParams( editTextWidth, TableRow.LayoutParams.WRAP_CONTENT ); // 可选:添加margin让布局更美观 editParams.setMargins(2, 2, 2, 2); ed.setLayoutParams(editParams); // 保留最小宽度防止内容溢出 ed.setMinWidth(editTextWidth); tr.addView(ed); } tl.addView(tr); } }
方案二:替换为RecyclerView(更现代化的方案)
如果你的项目允许,用RecyclerView配合横向LinearLayoutManager和自定义Item布局,能更好地适配全版本,而且性能更优:
- 每个TableRow作为RecyclerView的一个Item
- 给RecyclerView设置
LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)实现横向滚动 - 这种方案避免了TableLayout和HorizontalScrollView的兼容性问题,同时支持更多自定义功能
不过这个方案需要重构部分代码,适合需要长期维护的项目。
为什么方案一有效?
在Lollipop中,HorizontalScrollView会让TableLayout的可用宽度变成“无限”,导致系统的拉伸列逻辑失效。手动设置每个EditText的固定宽度后,TableLayout能准确计算每行的总宽度,让HorizontalScrollView可以正常滚动,同时每个EditText的大小保持一致,达到和拉伸列相同的视觉效果。
内容的提问来源于stack exchange,提问作者novice_2

