首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android 自定義組合控件接入 ListView 完整實戰指南

     編輯:程式設計綜合問答

架構選型:組合控件作為 Item 佈局

自定義 ViewGroup(如 RelativeLayout 子類)封裝內部子 View 及邏輯,作為 ListView 的單個 Item 佈局。核心優勢:封裝性強、復用性高、邏輯內聚。

實現步驟

1. 定義組合控件

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); }
}

2. 自定義 BaseAdapter

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 標準實現...
}

3. Activity/Fragment 中接入

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();
});

關鍵優化點

  • ViewHolder 模式:組合控件本身即 ViewHolder,無需額外標籤,convertView 直接復用。
  • 避免在 getView 中 new LayoutInflater:構造器傳入或靜態獲取。
  • 按鈕點擊回調:介面回調傳遞 position,避免在匿名類中捕獲位置導致錯亂。
  • 複雜佈局考慮 RecyclerView:ListView 已停止維護,新項目建議直接用 RecyclerView + ViewHolder,組合控件邏輯完全通用。

常見坑點

掌握組合控件 + Adapter 模式,可構建高度可維護的複雜列表 UI。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
問題原因修正
項目內容顯示錯亂convertView 復用時未重新 bindData每次 getView 必須調用 bindData 更新所有子 View
按鈕點擊響應錯誤位置匿名類捕獲舊 position使用介面回調並在 bindData 時設置 listener 與 position
EditText 輸入焦點異常ListView 預設焦點模式listView.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS)