自定義 `TopBar` 在 XML 中使用 `findViewById` 返回 null,或監聽器 `listener` 為 null 導致點擊崩潰。
View 在 XML 中膨脹時,**系統調用雙參構造器 `View(Context, AttributeSet)`**。代碼中只有單參構造器,導致屬性解析失敗、子 View 未初始化。
public class TopBar extends RelativeLayout {
// ... 成員變量
// 1. 代碼 new 時調用
public TopBar(Context context) {
this(context, null);
}
// 2. XML 膨脹時調用(關鍵!)
public TopBar(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
// 3. 樣式屬性時調用
public TopBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
LayoutInflater.from(context).inflate(R.layout.layout_top_bar, this, true);
ibtLeft = findViewById(R.id.ibt_left);
ibtRight = findViewById(R.id.ibt_right);
tvTitle = findViewById(R.id.tv_title);
// 設置內部點擊轉發給外部監聽器
ibtLeft.setOnClickListener(v -> { if (listener != null) listener.onLeftButtonClick(); });
ibtRight.setOnClickListener(v -> { if (listener != null) listener.onRightButtonClick(); });
}
// 監聽器接口與設置方法同前
}
<com.example.TopBar
android:id="@+id/topBar"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
TopBar topBar = findViewById(R.id.topBar); // 現在不再為 null
topBar.setOnTopBarClickListener(new TopBar.OnClickListener() {
@Override public void onLeftButtonClick() { Toast.makeText(this, "Left", Toast.LENGTH_SHORT).show(); }
@Override public void onRightButtonClick() { Toast.makeText(this, "Right", Toast.LENGTH_SHORT).show(); }
});