XML 中 GridLayout 設定 layout_columnWeight/layout_rowWeight 在 API 21+ 才支援,且行為不穩定。計算機鍵盤等等寬佈局需求無法靠 XML 靜態屬性解決。
// 工具類:取得螢幕寬度
public class ScreenUtils {
public static int getScreenWidth(Context context) {
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics dm = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(dm);
return dm.widthPixels;
}
}
// Activity/Fragment 中動態加載 GridLayout 子視圖
final int COL_COUNT = 4; // 計算機 4 列
GridLayout grid = findViewById(R.id.gridLayout);
grid.setColumnCount(COL_COUNT);
grid.setRowCount(5); // 視按鈕行數
for (int i = 0; i < buttonLabels.length; i++) {
View btn = LayoutInflater.from(this).inflate(R.layout.btn_key, grid, false);
((TextView) btn.findViewById(R.id.tv_label)).setText(buttonLabels[i]);
// 關鍵:寬度 = 螢幕寬度 / 列數,高度包裹內容
GridLayout.LayoutParams lp = new GridLayout.LayoutParams();
lp.width = ScreenUtils.getScreenWidth(this) / COL_COUNT;
lp.height = GridLayout.LayoutParams.WRAP_CONTENT;
lp.setGravity(Gravity.FILL_HORIZONTAL);
lp.columnSpec = GridLayout.spec(GridLayout.UNDEFINED, 1f); // 權重 1
lp.rowSpec = GridLayout.spec(GridLayout.UNDEFINED, 1f);
btn.setLayoutParams(lp);
grid.addView(btn);
}
lp.width = screenWidth / COL_COUNT:強制像素寬度,繞過權重機制不可靠問題。lp.columnSpec/rowSpec = spec(UNDEFINED, 1f):仍宣告權重 1,配合固定寬度雙重保障。Gravity.FILL_HORIZONTAL:子視圖內部內容水平置中/填滿。GridLayout.LayoutParams.setMargins() 並相應減少 lp.width。val colCount = 4
val btnWidth = resources.displayMetrics.widthPixels / colCount
gridLayout.columnCount = colCount
buttonLabels.forEachIndexed { idx, label ->
val btn = layoutInflater.inflate(R.layout.btn_key, gridLayout, false).apply {
findViewById(R.id.tv_label).text = label
layoutParams = GridLayout.LayoutParams().apply {
width = btnWidth
height = GridLayout.LayoutParams.WRAP_CONTENT
setGravity(Gravity.FILL_HORIZONTAL)
columnSpec = GridLayout.spec(GridLayout.UNDEFINED, 1f)
rowSpec = GridLayout.spec(GridLayout.UNDEFINED, 1f)
}
}
gridLayout.addView(btn)
}
現代佈局首選 ConstraintLayout,用 Guideline 等分螢幕,再建立水平鏈,XML 即可完成等寬佈局,效能優於巢狀 GridLayout/LinearLayout。