前言
如果只是簡單的清單呈現可以利用ArrayAdapter、SimpleCursorAdapter、SimpleAdapter來達成你的目的,但如果要做到更複雜清單呈現就必須用BaseAdapter來客製化ListView,利用BaseAdapter能更彈性的控制ListView 每個Item的內容與樣式。
- ArrayAdapter – ListView 簡易用法
- SimpleCursorAdapter
- SimpleAdapter – ListView 進階用法 -,簡易客製化ListView Item樣式
- BaseAdapter (此篇) – ListView 進階用法,完整客製化ListView Item樣式
針對實作BaseAdapter這邊來個簡單步驟說明:
- 建立一個ListView Item的Layout
- 實作BaseAdapter,根據資料來改變ListView Item
- 結果,取得清單資料丟到BaseAdapter
1.建立ListItem Layout
在res/layout建立一個ListView Itme的樣板,命名為style_listview.xml(自行定義),可依照自求需求設計,這邊就簡單拉兩個TextView來實作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#DEF8FF"> <LinearLayout android:id="@+id/llBorder" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="5dp"> <TextView android:id="@+id/tvLocal" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="2" android:text="TextView" android:textColor="@android:color/black" android:textSize="20sp" /> <TextView android:id="@+id/tvName" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:text="TextView" android:textColor="@android:color/black" android:textSize="20sp" /> </LinearLayout> </LinearLayout> |
2.實作BaseAdapter
這邊就是我們的重頭戲,先建立一個java類別命名為ViewAdapter.java(自行定義),將此類別繼承BaseAdapter,繼承BaseAdapter後會出現幾個方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
//取得Item的數量,通常用於取得資料集合的大小或數量 @Override public int getCount() { return 0; } //回傳Item的資料 @Override public Object getItem(int position) { return null; } //回傳Item的ID @Override public long getItemId(int position) { return position; } //回傳處理後的ListItem畫面,這個地方謹慎處理如不小心會發生很多錯誤 @Override public View getView(int position, View convertView, ViewGroup parent) { return null; } |
在開始實作BaseAdapter前請先想一下架構,我們ListView要input什麼樣的資料形態例如ArrayList、Map、Cursor…等,因為這關係到你的後需處理,以下範例input就用二維陣列來呈現,內容大概是顯示六都及政府所在如下。
- 臺北
- 信義區
- 新北
- 板橋區
- 桃園
- 桃園區
- 臺中
- 西屯區
- 臺南
- 安平區
- 新營區
- 高雄
- 苓雅區
- 鳳山區
想好架構後就直接看程式碼如何實作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
package test.com.demo; import android.graphics.Color; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.LinearLayout; import android.widget.TextView; public class ViewAdapter extends BaseAdapter { private String[][] ElementsData ; //資料 private LayoutInflater inflater; //加載layout private int indentionBase; //item缩排 //優化Listview 避免重新加載 //這邊宣告你會動到的Item元件 static class ViewHolder{ LinearLayout rlBorder; TextView Name; TextView Local; } //初始化 public ViewAdapter(String[][] data, LayoutInflater inflater){ this.ElementsData = data; this.inflater = inflater; indentionBase = 100; } //取得數量 @Override public int getCount() { return ElementsData.length; } //取得Item @Override public Object getItem(int position) { return ElementsData[position]; } //此範例沒有特別設計ID所以隨便回傳一個值 @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; //當ListView被拖拉時會不斷觸發getView,為了避免重複加載必須加上這個判斷 if (convertView == null) { holder = new ViewHolder(); convertView = inflater.inflate(R.layout.style_listview, null); holder.Name = (TextView) convertView.findViewById(R.id.tvName); holder.Local = (TextView) convertView.findViewById(R.id.tvLocal); holder.rlBorder = (LinearLayout) convertView.findViewById(R.id.llBorder); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } //1=都市 2=政府所在地 //不同類型用不同Style的表現方式 if (ElementsData[position][0].equals("1")){ holder.Local.setText("★"); holder.Name.setText(ElementsData[position][1]); holder.rlBorder.setBackgroundColor(Color.parseColor("#FFDBC9")); }else{ holder.Local.setText(""); holder.Name.setText(ElementsData[position][1]); LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) holder.rlBorder.getLayoutParams(); lp.setMargins(indentionBase,0, 0,0);//縮牌 } return convertView; } } |
3.結果
最後實作主程式把資料塞到BaseAdapter,看看執行結果如何
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
package test.com.demo; import android.content.Context; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.widget.AdapterView; import android.widget.ListView; import android.widget.Toast; public class MainActivity extends AppCompatActivity { //ListView 要顯示的內容 public String[][] data = { {"1","臺北市"}, {"2","信義區"}, {"1","新北市"}, {"2","板橋區"}, {"1","桃園市"}, {"2","桃園區"}, {"1","臺中市"}, {"2","西屯區"}, {"1","臺南市"}, {"2","安平區"}, {"2","新營區"}, {"1","高雄市"}, {"2","苓雅區"}, {"2","鳳山區"} }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ListView listview = (ListView) findViewById(R.id.listview); LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); ViewAdapter adapter = new ViewAdapter(data,inflater); listview.setAdapter(adapter); listview.setOnItemClickListener(onClickListView); //指定事件 Method } /*** * 點擊ListView事件Method */ private AdapterView.OnItemClickListener onClickListView = new AdapterView.OnItemClickListener(){ @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Toast.makeText(MainActivity.this,"點選第 "+(position +1) +" 個 \n內容:"+data[position][1], Toast.LENGTH_SHORT).show(); } }; } |
感謝,說明得很清楚
請問要是我的佈局是 spinner, 下方接一個動態的ListView, 由spinner選取後,以一個按鈕將所選的顯示在動態的ListView, 為何我做出的結果是 item1:泡麵(spinner), 再按一次按鈕變 item2:泡麵(spinner), 但若選炒麵(spinner),會是 item3:炒麵(spinner),但前面的 item1:炒麵及 item2:炒麵,都變成一樣了,問題???請求達人幫忙
應該是你的OnItemClickListener程式有寫錯,但是看不到你的程式碼無法確定真正原因
你好,感謝你的分享使我更了解ListView運作
同時也想請教;這個方法若是需要修改特定的item的話要從哪邊處理呢?
謝謝