雖然現代開發推薦使用 XML 佈局或 Jetpack Compose,但特定場景(動態產生表單、跑馬燈、插件系統)仍需以程式碼建立 RelativeLayout。關鍵在於正確設定 LayoutParams 並呼叫 addRule() 建立相對定位關係。
RelativeLayout 容器RelativeLayout.LayoutParamsaddRule() 設定相對規則(如 ALIGN_PARENT_TOP, RIGHT_OF, BELOW 等)addView(view, params)setContentView(rootLayout, rootParams)
public class DynamicLayoutActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 1. 根佈局
RelativeLayout root = new RelativeLayout(this);
RelativeLayout.LayoutParams rootParams = new RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
);
// 2. 按鈕 A
Button btnA = new Button(this);
btnA.setId(View.generateViewId()); // API 17+ 自動生成唯一 ID
btnA.setText("按鈕 A");
RelativeLayout.LayoutParams paramsA = new RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
);
paramsA.addRule(RelativeLayout.ALIGN_PARENT_TOP);
paramsA.addRule(RelativeLayout.ALIGN_PARENT_START);
root.addView(btnA, paramsA);
// 3. 按鈕 B:置於 A 右側
Button btnB = new Button(this);
btnB.setText("按鈕 B");
RelativeLayout.LayoutParams paramsB = new RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
);
paramsB.addRule(RelativeLayout.ALIGN_PARENT_TOP);
paramsB.addRule(RelativeLayout.RIGHT_OF, btnA.getId()); // 關鍵:相對 A 定位
root.addView(btnB, paramsB);
// 4. 設定內容視圖
setContentView(root, rootParams);
}
}
| 規則常數 | 含義 | 參數 |
|---|---|---|
| ALIGN_PARENT_TOP/BOTTOM/START/END | 貼齊父容器邊緣 | 無 |
| CENTER_IN_PARENT / CENTER_HORIZONTAL / CENTER_VERTICAL | 置中 | 無 |
| LEFT_OF / RIGHT_OF / ABOVE / BELOW | 相對另一視圖定位 | 目標視圖 ID |
| ALIGN_TOP / ALIGN_BOTTOM / ALIGN_START / ALIGN_END | 對齊另一視圖邊緣 | 目標視圖 ID |
原始碼片段中 m_btnCrown.getId() 若未手動設定 ID 則為 NO_ID (-1),導致 RIGHT_OF 失效。修正:
// 建立視圖後立即指派 ID
m_btnCrown.setId(View.generateViewId()); // 或 ViewCompat.generateViewId()
// 後續規則才能正確引用
lp.addRule(RelativeLayout.RIGHT_OF, m_btnCrown.getId());
LayoutInflater.inflate(),效能較好且易維護。View.generateViewId() 避免 ID 衝突。RecyclerView + Adapter 模式。掌握程式碼建立 RelativeLayout 技巧,能應對高度動態化的 UI 需求。