自定義 ViewGroup(如 RelativeLayout 子類)封裝內部子 View 及邏輯,作為 ListView 的單個 Item 佈局。核心優勢:封裝性強、復用性高、邏輯內聚。
public class CustomItemView extends RelativeLayout {
private TextView tvNumber;
private EditText etContent;
private Button btnMark, btnDelete;
private int position;
public CustomItemView(Context context, int position) {
super(context);
this.position = position;
init(context);
}
private void init(Context context) {
inflate(context, R.layout.item_custom, this); // 關鍵:inflate 到 this
tvNumber = findViewById(R.id.tv_number);
etContent = findViewById(R.id.et_content);
btnMark = findViewById(R.id.btn_mark);
btnDelete = findViewById(R.id.btn_delete);
tvNumber.setText("項目 " + (position + 1));
// 綁定按鈕點擊回調介面...
}
// 對外暴露資料綁定方法
public void bindData(ItemData data) { ... }
public interface OnActionListener { void onMark(int pos); void onDelete(int pos); }
}
public class CustomAdapter extends BaseAdapter {
private List dataList;
private LayoutInflater inflater;
private CustomItemView.OnActionListener listener;
@Override
public View getView(int position, View convertView, ViewGroup parent) {
CustomItemView itemView;
if (convertView instanceof CustomItemView) {
itemView = (CustomItemView) convertView;
} else {
itemView = new CustomItemView(parent.getContext(), position);
}
itemView.bindData(dataList.get(position));
itemView.setOnActionListener(listener);
return itemView;
}
// getCount, getItem, getItemId 標準實現...
}
ListView listView = findViewById(R.id.list_view);
CustomAdapter adapter = new CustomAdapter(dataList);
adapter.setOnActionListener(new CustomItemView.OnActionListener() {
@Override public void onMark(int pos) { /* 標記邏輯 */ }
@Override public void onDelete(int pos) { dataList.remove(pos); adapter.notifyDataSetChanged(); }
});
listView.setAdapter(adapter);
// 動態添加按鈕點擊
btnAdd.setOnClickListener(v -> {
dataList.add(new ItemData("新項目"));
adapter.notifyDataSetChanged();
});
convertView 直接復用。RecyclerView + ViewHolder,組合控件邏輯完全通用。| 問題 | 原因 | 修正 |
|---|---|---|
| 項目內容顯示錯亂 | convertView 復用時未重新 bindData | 每次 getView 必須調用 bindData 更新所有子 View |
| 按鈕點擊響應錯誤位置 | 匿名類捕獲舊 position | 使用介面回調並在 bindData 時設置 listener 與 position |
| EditText 輸入焦點異常 | ListView 預設焦點模式 | listView.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS) |