學習筆記 - Custom ListView UI


繼這篇: Android 學習筆記 - 建立簡單的 ListView
今天抽空找一下資料,試著實作自定義 ListView 的 row UI

只記實作內容,詳細原理後查後補~

項目

主要分成以下三個部分

  • 建立 UI 的 XML
  • 建立 Adapter 連結 UI 的 xml
  • 建立 View Holder 讓 UI instance 可以重用

建立 UI 的 XML

這時候在專案的 layout 區塊下面新增一個 row.xml ,名稱可自定義。

經過編輯之後,裡面長這樣:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Header"
        android:textSize="20dp"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/textView"/>

</LinearLayout>

建立 Adapter 和 View Holder

這個 Adapter 是要加給 ListView instance 使用的,
在左側專案的 java 目錄下的專案區塊新增一個 MyAdapter.java ,檔名一樣可自定義。

而使用 View Holder 的原因在此 → 參照
詳細的運作原理和 LayoutInflater 是什麼東西等等的還要再研究研究。

完成後長這樣:

public class MyAdapter extends BaseAdapter {
    Context context;
    String[] data;
    private static LayoutInflater inflater = null;

    public MyAdapter(Context context, String[] data) {
        this.context = context;
        this.data = data;
        inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    @Override
    public int getCount() {
        return  data.length;
    }

    @Override
    public Object getItem(int position) {
        return data[position];
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final ViewHolder viewHolder;
        viewHolder = new ViewHolder();

        if (convertView == null) {
            convertView =  inflater.inflate(R.layout.row, parent, false);
            // 把拿到的 textView 設定進 view holder
            viewHolder.textView = (TextView)convertView.findViewById(R.id.textView);
        } else {
            convertView.setTag(viewHolder);
        }

        viewHolder.textView.setText(data[position]);

        return convertView;
    }

    static class ViewHolder {
        TextView textView;
    }
}

整合使用

這時候在 ListView 的所在地就可以這樣用:

先宣告:

ListView listView;
ListAdapter listAdapter;

接著把剛剛新建的 MyAdapter 設定給 listView

listView = (ListView)findViewById(R.id.listView);
listAdapter = new MyAdapter(this, new String[]{"a", "b", "c"});
listView.setAdapter(listAdapter);

成果長這樣: