自定义ListView【通用】适配器并实现监听控件
ListView:在Android應用開發過程中屬于最常用的系統組件之一,當然可能童鞋們問為什么會突然游戲開發中講這個,呵呵,其實在游戲開發中,也會常常使用到系統組件,比如游戲排行榜,簡單的游戲關卡選擇等等,都可以來使用ListView來實現。
當然關于ListView我想大家都會使用了,那么這篇文章也不是跟大家講解ListView是如果使用的,而是如何實現自定義一個【通用】適配器類。
在ListView三種適配器當中,最受大家青睞的肯定就是SimpleAdapter適配器,用過的童鞋們都很清楚,它的擴展性很強,可以將ListView中每一項都使用自定義布局,插入N多組件;但是SimpleAdapter也有弱點,那就是當ListView中每一項有Button、CheckBox等這些有事件的組件,我們想監聽它們就必須自定義適配器!那么今天的重點也就是來講解一下如何寫一個自定義通用適配器類!
SimpleAdapter 構造的時候,我們知道需要五個參數來進行映射數據到ListView中,那么我們今天的自定義通用適配器其實也就是實現系統SimpleAdapter的一個自定義版。
OK,可能我說這么多,大家還是不太懂,其實今天要講述的自定義通用適配器優點有三點:
1.使用通用適配器就不需要每次使用自定義適配器的時候,都要去重新去寫一個,太累。。。。
2.構造方法與SimpleAdapter構造方法相同,五個參數也一摸一樣!
3.只需要在自定義的適配器類中,將我們需要監聽的組件進行設置監聽即可!別的代碼不需要去改動!
例如我們需要完成下圖這種自定義ListView:
(圖1)
首先我們來完成ListView中每項的布局:
main.xml:
<?xml?version="1.0"?encoding="utf-8"?> <LinearLayout?xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent"> <ImageView android:id="@+id/iv" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <LinearLayout android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="wrap_content"> <TextView android:id="@+id/bigtv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="20sp" /> <TextView android:id="@+id/smalltv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="10sp" /> </LinearLayout> <Button android:id="@+id/btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="button" /> <CheckBox android:id="@+id/cb" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>
修改源碼: MainActivity.java :
public?class?MainActivity?extends?Activity { private?SimpleAdapter adapter;// 聲明適配器對象 private?ListView listView;?// 聲明列表視圖對象 private?List<Map<String, Object>> list;// 聲明列表容器 public?static?MainActivity ma; @Override public?void?onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ma =?this; // 實例化列表容器 list =?new?ArrayList<Map<String, Object>>(); listView =?new?ListView(this);// 實例化列表視圖 // 實例一個列表數據容器 Map<String, Object> map =?new?HashMap<String, Object>(); // 往列表容器中添加數據 map.put("item1_imageivew", R.drawable.icon); map.put("item1_bigtv",?"BIGTV"); map.put("item1_smalltv",?"SMALLTV"); // 將列表數據添加到列表容器中 list.add(map); // --使用系統適配器,無法實現組件監聽; // //實例適配器 adapter =?new?SimpleAdapter(this, list, R.layout.main,?new?String[] { "item1_imageivew",?"item1_bigtv",?"item1_smalltv"?},?new?int[] { R.id.iv, R.id.bigtv, R.id.smalltv }); listView.setAdapter(adapter); // //顯示列表視圖 this.setContentView(listView); } }
到此,我們之前要求完成的(圖1)要求的ListView,[對ListView不太熟悉的童鞋自行百度google先學習一下基礎吧。
當然這里我們只是完成了界面,如果想監聽(圖1)中的按鈕和復選框事件,那么我們肯定需要自定義一個適配器,那么下面開始介紹如何實現通用適配器:
創建一個新類,類名:“MySimpleAdapter.java”繼承BaseAdapter:
package?com.himi; import?java.util.List; import?java.util.Map; import?android.app.AlertDialog; import?android.content.Context; import?android.view.LayoutInflater; import?android.view.View; import?android.view.ViewGroup; import?android.widget.BaseAdapter; import?android.widget.Button; import?android.widget.CheckBox; import?android.widget.CompoundButton; import?android.widget.ImageView; import?android.widget.TextView; import?android.widget.CompoundButton.OnCheckedChangeListener; public?class?MySimpleAdapter?extends?BaseAdapter { private?LayoutInflater mInflater; private?List<Map<String, Object>> list; private?int?layoutID; private?String flag[]; private?int?ItemIDs[]; public?MySimpleAdapter(Context context, List<Map<String, Object>> list, int?layoutID, String flag[],?int?ItemIDs[]) { this.mInflater = LayoutInflater.from(context); this.list = list; this.layoutID = layoutID; this.flag = flag; this.ItemIDs = ItemIDs; } @Override public?int?getCount() { // TODO Auto-generated method stub return?list.size(); } @Override public?Object getItem(int?arg0) { // TODO Auto-generated method stub return?0; } @Override public?long?getItemId(int?arg0) { // TODO Auto-generated method stub return?0; } @Override public?View getView(int?position, View convertView, ViewGroup parent) { convertView = mInflater.inflate(layoutID,?null); for?(int?i =?0; i < flag.length; i++) {// 備注1 if?(convertView.findViewById(ItemIDs[i])?instanceof?ImageView) { ImageView iv = (ImageView) convertView.findViewById(ItemIDs[i]); iv.setBackgroundResource((Integer) list.get(position).get( flag[i])); }?else?if?(convertView.findViewById(ItemIDs[i])?instanceof?TextView) { TextView tv = (TextView) convertView.findViewById(ItemIDs[i]); tv.setText((String) list.get(position).get(flag[i])); }?else?{ // ...備注2 } } addListener(convertView); return?convertView; } /** * 童鞋們只需要將需要設置監聽事件的組件寫在下面這方法里就可以啦! 別的不需要修改! 備注3 */ public?void?addListener(View convertView) { ((Button) convertView.findViewById(R.id.btn)) .setOnClickListener(new?View.OnClickListener() { @Override public?void?onClick(View v) { new?AlertDialog.Builder(MainActivity.ma) .setTitle("自定義通用SimpleAdapter") .setMessage("按鈕成功觸發監聽事件!").show(); } }); ((CheckBox) convertView.findViewById(R.id.cb)) .setOnCheckedChangeListener(new?OnCheckedChangeListener() { @Override public?void?onCheckedChanged(CompoundButton buttonView, boolean?isChecked) { new?AlertDialog.Builder(MainActivity.ma) .setTitle("自定義通用SimpleAdapter") .setMessage("CheckBox成功觸發狀態改變監聽事件!").show(); } }); } }備注1:這個For循環中是對ListView中每一項中包含所有的組件進行判定每個組件的類型,從而去設置其數據!
其中 《instanceof》這個關鍵字可能有的童鞋不太熟習,這個是對Object 類型的判斷;
這里我只是對ImageView、TextView的類型進行的數據識別,為什么我這里只寫了這兩種,那是因為Button、CheckBox等這些帶事件響應的組件是無法通過適配器映射到ListView上的;
其實關于適配器映射的機制,這里簡單說下:例如一個TextView組件,那么在ListView的每一項(List)中put()添加的時候,put()方法中第一個參數key大家知道是用于與適配器進行對應映射數據用的值,那么第二個參數其實就是put進組件的數據;其實當其數據反射在ListViw時,其實內部就是對組件進行實例化,并且對組件設置數據;
備注2:我這里最后還有一個else{...}這里是留給童鞋們去擴展的,因為可能還有一些其他能映射的組件,所以這里留下接口,供大家擴展;
備注3:addListener(View convertView)這是我留出來的方法,童鞋們只需要將需要設置監聽事件的組件寫在這方法里就可以啦!
那么看一下我們使用通用監聽控件的效果吧:
OK,很正常!那么在來看看使用系統的SimpleAdapter 與我們自定義的MySimpleAdapter代碼對比圖:
怎么樣!構造參數完全一樣,而且我們這個比它強大,我們只要去設置下需要監聽的組件監聽代碼就OK了。
娃哈哈,好啦,今天就到這里吧,希望此通用適配器對大家有用!
補充:大家使用自定義適配器的時候,有時候ListView每一項的焦點沒有了,比如本文中是因為Button和CheckBox截獲了焦點,童鞋們只要將button和checkBox的焦點設置不可見就OK啦。~
xml中focusable是這個屬性; android:focusable="false"
總結
以上是生活随笔為你收集整理的自定义ListView【通用】适配器并实现监听控件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android之自定义Adapter的L
- 下一篇: ListView通过自定义适配器来显示数