李華明Himi 原創,轉載務必在明顯處註明:
轉載自【黑米GameDev街區】 原文連結: http://www.himigame.com/android-game/374.html
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"?><br /><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"<br /> android:orientation="horizontal"<br /> android:layout_width="fill_parent"<br /> android:layout_height="fill_parent"<br /> ><br /><ImageView<br /> android:layout_width="wrap_content"<br /> android:layout_height="wrap_content"<br /> android:id="@+id/iv"<br /> /><br /> <LinearLayout<br /> android:orientation="vertical"<br /> android:layout_width="wrap_content"<br /> android:layout_height="wrap_content"<br /> ><br /><TextView<br /> android:layout_width="wrap_content"<br /> android:layout_height="wrap_content"<br /> android:textSize="20sp"<br /> android:id="@+id/bigtv"<br /> /><br /><TextView<br /> android:layout_width="wrap_content"<br /> android:layout_height="wrap_content"<br /> android:textSize="10sp"<br /> android:id="@+id/smalltv"<br /> /><br /> </LinearLayout><br /><Button<br /> android:layout_width="wrap_content"<br /> android:layout_height="wrap_content"<br /> android:text="button"<br /> android:id="@+id/btn"<br /> /><br /><CheckBox<br /> android:layout_width="wrap_content"<br /> android:layout_height="wrap_content"<br /> android:id="@+id/cb"<br /> /><br /></LinearLayout><br />
修改源碼:MainActivity.java:
public class MainActivity extends Activity {<br />private SimpleAdapter adapter;// 聲明配接器物件<br />private ListView listView; // 聲明列表視圖對象<br />private List<Map<String, Object>> list;// 聲明列表容器<br />public static MainActivity ma;<br />@Override<br />public void onCreate(Bundle savedInstanceState) {<br />super.onCreate(savedInstanceState);<br />ma = this;<br />// 執行個體化列表容器<br />list = new ArrayList<Map<String, Object>>();<br />listView = new ListView(this);// 執行個體化列表視圖<br />// 執行個體一個列表資料容器<br />Map<String, Object> map = new HashMap<String, Object>();<br />// 往列表容器中添加資料<br />map.put("item1_imageivew", R.drawable.icon);<br />map.put("item1_bigtv", "BIGTV");<br />map.put("item1_smalltv", "SMALLTV");<br />// 將列表資料添加到列表容器中<br />list.add(map);<br />// --使用系統適配器,無法實現組件監聽;<br />// //執行個體適配器<br />adapter = new SimpleAdapter(this, list, R.layout.main, new String[] {<br />"item1_imageivew", "item1_bigtv", "item1_smalltv" }, new int[] {<br />R.id.iv, R.id.bigtv, R.id.smalltv });<br />listView.setAdapter(adapter);<br />// //顯示列表視圖<br />this.setContentView(listView);<br />}<br />}
到此,我們之前要求完成的(圖1)要求的ListView,[對ListView不太熟悉的童鞋自行百度google先學習一下基礎吧]
當然這裡我們只是完成了介面,如果想監聽(圖1)中的按鈕和複選框事件,那麼我們肯定需要自訂一個適配器,那麼下面開始介紹如何?通用適配器:
建立一個新類,類名:“MySimpleAdapter.java”繼承BaseAdapter:
/**<br /> *<br /> */<br />package com.himi;<br />import java.util.List;<br />import java.util.Map;<br />import android.app.AlertDialog;<br />import android.content.Context;<br />import android.view.LayoutInflater;<br />import android.view.View;<br />import android.view.ViewGroup;<br />import android.widget.BaseAdapter;<br />import android.widget.Button;<br />import android.widget.CheckBox;<br />import android.widget.CompoundButton;<br />import android.widget.ImageView;<br />import android.widget.TextView;<br />import android.widget.CompoundButton.OnCheckedChangeListener;<br />/**<br /> * @author Himi<br /> *<br /> */<br />public class MySimpleAdapter extends BaseAdapter {<br />private LayoutInflater mInflater;<br />private List<Map<String, Object>> list;<br />private int layoutID;<br />private String flag[];<br />private int ItemIDs[];<br />public MySimpleAdapter(Context context, List<Map<String, Object>> list,<br />int layoutID, String flag[], int ItemIDs[]) {<br />this.mInflater = LayoutInflater.from(context);<br />this.list = list;<br />this.layoutID = layoutID;<br />this.flag = flag;<br />this.ItemIDs = ItemIDs;<br />}<br />@Override<br />public int getCount() {<br />// TODO Auto-generated method stub<br />return list.size();<br />}<br />@Override<br />public Object getItem(int arg0) {<br />// TODO Auto-generated method stub<br />return 0;<br />}<br />@Override<br />public long getItemId(int arg0) {<br />// TODO Auto-generated method stub<br />return 0;<br />}<br />@Override<br />public View getView(int position, View convertView, ViewGroup parent) {<br />convertView = mInflater.inflate(layoutID, null);<br />for (int i = 0; i < flag.length; i++) {//備忘1<br />if (convertView.findViewById(ItemIDs[i]) instanceof ImageView) {<br />ImageView iv = (ImageView) convertView.findViewById(ItemIDs[i]);<br />iv.setBackgroundResource((Integer) list.get(position).get(<br />flag[i]));<br />} else if (convertView.findViewById(ItemIDs[i]) instanceof TextView) {<br />TextView tv = (TextView) convertView.findViewById(ItemIDs[i]);<br />tv.setText((String) list.get(position).get(flag[i]));<br />}else{<br />//...備忘2<br />}<br />}<br />addListener(convertView);<br />return convertView;<br />}<br />/**<br /> * 童鞋們只需要將需要設定監聽事件的組件寫在下面這方法裡就可以啦!<br /> * 別的不需要修改!<br /> * 備忘3<br /> */<br />public void addListener(View convertView) {<br />((Button)convertView.findViewById(R.id.btn)).setOnClickListener(<br />new View.OnClickListener() {<br />@Override<br />public void onClick(View v) {<br />new AlertDialog.Builder(MainActivity.ma)<br />.setTitle("自訂通用SimpleAdapter")<br />.setMessage("按鈕成功觸發監聽事件!")<br />.show();<br />}<br />});<br />((CheckBox)convertView.findViewById(R.id.cb)).<br />setOnCheckedChangeListener(new OnCheckedChangeListener() {<br />@Override<br />public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {<br />new AlertDialog.Builder(MainActivity.ma)<br />.setTitle("自訂通用SimpleAdapter")<br />.setMessage("CheckBox成功觸發狀態改變監聽事件!")<br />.show();<br />}<br />});<br />}<br />}
備忘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"
這裡也提醒一下開發遊戲的童鞋們,很多遊戲開發人員認為開發遊戲不用去學習系統組件的使用,不用去沾染xml、布局啥的,其實這麼想的童鞋們你們就大錯特錯了,Android之所以能這麼火,其組件的美觀佔了很重的份量,這麼美的組件不用豈不是很浪費!!希望童鞋們對組件不熟悉的遊戲開發人員都要去學習學習下組件的使用!
源碼下載: http://www.himigame.com/android-game/374.html