FrameLayout 包裹 ViewFlipper,ViewFlipper 管理多個子頁面 (含 Button、SeekBar)。在 Activity 方法 `onLock(View v)` 中動態 `setEnabled(false)` 禁用子頁面按鈕,**代碼執行無報錯但介面按鈕仍可點擊**。同樣代碼操作 Activity 根佈局上的 Button 則正常生效。
public void onLock(View v) {
// ...
View view = LayoutInflater.from(this).inflate(R.layout.tab3, null); // ❌ 關鍵錯誤:重新 inflate 產生新 View 樹
if (bIsLocked) {
((Button)view.findViewById(R.id.BntTab3Fun01)).setEnabled(false);
// ...
}
}
View childPage = viewFlipper.getChildAt(targetIndex); // 0-based
Button btn = childPage.findViewById(R.id.BntTab3Fun01);
btn.setEnabled(false);
// 前提:所有子頁面的 Button ID 全局唯一 (不重複)
Button btn = findViewById(R.id.BntTab3Fun01); // 直接從 Activity 根找
btn.setEnabled(false);
View current = viewFlipper.getCurrentView();
Button btn = current.findViewById(R.id.BntTab3Fun01);
btn.setEnabled(false);
public class MainActivity extends AppCompatActivity {
private ViewFlipper viewFlipper;
private Button[] tab3Buttons = new Button[5]; // 持有引用
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewFlipper = findViewById(R.id.viewflipper);
// 動態添加頁面時同步持有引用
for (int i = 0; i < 3; i++) {
View page = LayoutInflater.from(this).inflate(R.layout.tab3, null);
tab3Buttons[0] = page.findViewById(R.id.BntTab3Fun01);
tab3Buttons[1] = page.findViewById(R.id.BntTab3Fun02);
// ...
viewFlipper.addView(page);
}
}
public void onLock(View v) {
bIsLocked = !bIsLocked;
for (Button btn : tab3Buttons) {
btn.setEnabled(!bIsLocked); // 直接操作持有的引用
}
}
}
// 這行從 setContentView 設置的視圖樹查找,找到的是真實顯示的 View
((Button)findViewById(R.id.BntLock)).setBackground(...); // ✅ 生效
因為 `setContentView` 只調用一次,視圖樹穩定,`findViewById` 能精準定位到螢幕上的實例。
| 坑位 | 徵兆 | 修正 |
|---|---|---|
| 重複 inflate 同一 layout | findViewById 找到舊實例、事件不觸發、狀態不同步 | inflate 一次、addView 一次、持有引用 |
| 子頁面 ID 重複 | findViewById 只返回第一個匹配 | ID 全局唯一、或用 getChildAt 索引定位 |
| 在 onCreate 前操作 ViewFlipper 子 View | NullPointerException | 確保 addView 後再操作 |
| ViewFlipper 未設定 LayoutParams | 子頁面不佔滿螢幕、顯示異常 | addView(view, new LayoutParams(MATCH_PARENT, MATCH_PARENT)) |
ViewFlipper 子頁面控件操作失效,90% 是「重複 inflate」導致操作了非顯示 View 實例。
鐵律:inflate → addView → 持有引用 → 後續只操作持有引用。切勿在事件處理中再次 `inflate` 同一佈局檔。