[Android] ListView

情境

在 5.0 以後多了一個 RecyclerView 
功能比 ListView 還強大 
重點是用起來跟 ListView 大同小異 
目前是全面取代 ListView 的利器 
可以參考http://givemepass.blogspot.tw/2015/12/recyclerview.html
如果 ListView 想塞圖、塞 Button 或者塞你想放進去的東西怎麼辦? 
利用 BaseAdapter 就可以輕鬆辦到

程式碼下載

你可以在 GitHub 觀看或下載完成程式碼
或者複製下面程式碼貼到對應的檔案 
一開始先宣告一個 ListView 在 xml 內 
main_activity layout.xml 部分
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">

    <ListView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</RelativeLayout>
MainActivity.java 主程式部分
public class MainActivity extends AppCompatActivity {
    private ListView mListView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mListView = (ListView) findViewById(R.id.list);
        mListView.setAdapter(new MyAdapter());
    }

    private class MyAdapter extends BaseAdapter{

        @Override
        public int getCount() {
            return 3;
        }

        @Override
        public Object getItem(int position) {
            return null;
        }

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

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View v = convertView;
            Holder holder;
            if(v == null){
                v = LayoutInflater.from(getApplicationContext()).inflate(R.layout.list_item, null);
                holder = new Holder();
                holder.image = (ImageView) v.findViewById(R.id.image);
                holder.text = (TextView) v.findViewById(R.id.text);

                v.setTag(holder);
            } else{
                holder = (Holder) v.getTag();
            }
            switch(position) {
                case 0:
                    holder.image.setImageResource(R.drawable.cat);
                    holder.text.setText("cat");
                    break;
                case 1:
                    holder.image.setImageResource(R.drawable.monkey);
                    holder.text.setText("monkey");
                    break;
                case 2:
                    holder.image.setImageResource(R.drawable.panda);
                    holder.text.setText("panda");
                    break;
            }
            return v;
        }
        class Holder{
            ImageView image;
            TextView text;
        }
    }
}
在我們的 BaseAdapter 內必須吃一個 row 的l ayout 
因此增加一個 adapter.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ImageView
        android:id="@+id/image"
        android:layout_centerVertical="true"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"/>

    <TextView
        android:id="@+id/text"
        android:layout_centerVertical="true"
        android:textSize="18sp"
        android:layout_marginLeft="20dp"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_toRightOf="@+id/image"
        android:textColor="#000000"/>

</RelativeLayout>
由於我們的 Layout 內有吃到一些圖檔 
可以從下面的連結下載放到 drawable 資料夾內 
https://github.com/givemepassxd999/blog_files/blob/master/drawable.zip

程式碼說明

首先我們了解一下什麼是 BaseAdapter 
BaseAdapter 是一個超好用的類別 它可以讓你自己定義許多種 View 
例如 Spinner, ListView, GridView 
那我們要怎麼去定義一個屬於自己的 ListView 呢?
增加一個新的類別叫做 MyAdapter 
並且繼承 BaseAdapter 
你會發現需要覆寫四個方法分別是
private class MyAdapter extends BaseAdapter{

    @Override
    public int getCount() {
        return 0;
    }

    @Override
    public Object getItem(int position) {
        return null;
    }

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        return null;
    }
}
IDE 會自動產生這四個方法 
這四個方法我來稍微解釋一下 
我們知道 ListView 是由一列一列所組成的 
而每一個列 我們可以將它看成是一個 View 
所組合起來的就是一整個 ListView 
所以 getCount() 就是可以取得到底有多少列的方法
而如果我們要取得某一列的內容 就是使用 getItem() 這個方法 
如果你想要取得某一列的 id 就使用 getItemId() 這個方法 
接著是我們最重要的一個方法 要做修改某一列 View 的內容 
就是利用 getView() 這個方法
首先先想好要將 ListView 改變成怎樣? 
假設我們想要先塞一個 Button 然後塞一張圖片 
最後在加上文字說明好了
增加一個 adapter.xml 
裡面就是放每一列 ListView 的內容 
根據我們想要的會放下 
由於我的 Layout 設定為 RelativeLayout 
因此會多一個關聯的屬性
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ImageView
        android:id="@+id/image"
        android:layout_centerVertical="true"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"/>

    <TextView
        android:id="@+id/text"
        android:layout_centerVertical="true"
        android:textSize="18sp"
        android:layout_marginLeft="20dp"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_toRightOf="@+id/image"
        android:textColor="#000000"/>

</RelativeLayout>
接著我們在 MyListView 裡面指定 main.xml 為一開始的畫面 
然後設定 MyAdapter 為 ListView 的 Adapter
private class MyAdapter extends BaseAdapter{

    @Override
    public int getCount() {
        return 3;
    }

    @Override
    public Object getItem(int position) {
        return null;
    }

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View v = convertView;
        Holder holder;
        if(v == null){
            v = LayoutInflater.from(getApplicationContext()).inflate(R.layout.list_item, null);
            holder = new Holder();
            holder.image = (ImageView) v.findViewById(R.id.image);
            holder.text = (TextView) v.findViewById(R.id.text);

            v.setTag(holder);
        } else{
            holder = (Holder) v.getTag();
        }
        switch(position) {
            case 0:
                holder.image.setImageResource(R.drawable.cat);
                holder.text.setText("cat");
                break;
            case 1:
                holder.image.setImageResource(R.drawable.monkey);
                holder.text.setText("monkey");
                break;
            case 2:
                holder.image.setImageResource(R.drawable.panda);
                holder.text.setText("panda");
                break;
        }
        return v;
    }
    class Holder{
        ImageView image;
        TextView text;
    }
}
接著換到 MyAdapter.java 
簡單的用三列 
因此我們將 return 設定為3
public int getCount() {
   return 3;
}
再來就是要取得 View 的順序 
先是 Button 再來是 ImageView 接著是 TextView 
所以我們宣告成一個類別讓該列的 setTag 屬性去讀取
class Holder{
    ImageView image;
    TextView text;
}
接著我們在getView 方法裡面去讀取它 
可以看到我們利用 Holder 在 getView 重複使用 
這邊可以參考 如何在ListView中使用Holder pattern來重用view 
再來就是設定三個元件上面的圖或文字
switch(position) {
    case 0:
        holder.image.setImageResource(R.drawable.cat);
        holder.text.setText("cat");
        break;
    case 1:
        holder.image.setImageResource(R.drawable.monkey);
        holder.text.setText("monkey");
        break;
    case 2:
        holder.image.setImageResource(R.drawable.panda);
        holder.text.setText("panda");
        break;
}
這樣一來全部設定好 
可以將該列的 View 回傳
return view;
最後在 MainActivity.java 使用這個 Adapter 就可以出現畫面了。
private ListView mListView;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mListView = (ListView) findViewById(R.id.list);
    mListView.setAdapter(new MyAdapter());
}

 


這樣就是一個簡單的客製化 ListView 的範例

轉自 : http://givemepass.blogspot.tw/2011/10/baseadapterlistview.html

留言

熱門文章