在 Android 程式碼中動態建立 RadioButton 並加入 RadioGroup 時,若錯誤地重複添加已存在於佈局中的 RadioGroup,會拋出「The specified child already has a parent」異常。
// XML 中已定義 RadioGroup
<RadioGroup android:id="@+id/rgc" ... ></RadioGroup>
// Java 代碼錯誤示範
RadioGroup rg = (RadioGroup) findViewById(R.id.rgc); // 獲取 XML 中已存在的 RadioGroup
// ... 建立 RadioButton 並加入 rg ...
LinearLayout l1 = (LinearLayout) findViewById(R.id.sl);
l1.addView(rg); // 錯誤:rg 已經有父視圖(XML 佈局),不能再次添加
findViewById() 返回的是 XML 佈局中已實例化並掛載到視圖樹的 View 物件。這個 RadioGroup 已經有父容器(LinearLayout),再次調用 parent.addView(child) 會導致衝突。
// 不在 XML 中定義 RadioGroup,完全由代碼建立
LinearLayout l1 = (LinearLayout) findViewById(R.id.sl);
RadioGroup rg = new RadioGroup(this); // 新建實例
rg.setOrientation(RadioGroup.VERTICAL);
RadioButton[] rb = new RadioButton[4];
for (int i = 0; i < 4; i++) {
rb[i] = new RadioButton(this);
rb[i].setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT));
rb[i].setText(i + " 選項");
rg.addView(rb[i]);
}
l1.addView(rg); // 只有這時才添加到父容器
// XML 保留 RadioGroup
// Java 代碼
RadioGroup rg = (RadioGroup) findViewById(R.id.rgc); // 直接使用,不要再 addView(rg)
for (int i = 0; i < 4; i++) {
RadioButton rb = new RadioButton(this);
rb.setText(i + " 選項");
rg.addView(rb); // 只添加 RadioButton 到現有 RadioGroup
}
// 移除 l1.addView(rg) 這行
findViewById() 獲取的 View 已經在視圖樹中,不可再次添加new View(context) 創建新實例LayoutParams) 必須匹配父容器類型若需動態移除並重新添加 View,必須先調用 parent.removeView(child) 再添加到新容器。