Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發實例 >> 【Android游戲開發二十三】自定義ListView【通用】適配器並實現監聽控件!

【Android游戲開發二十三】自定義ListView【通用】適配器並實現監聽控件!

編輯:Android開發實例

  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:

 

  1. <?xml version="1.0" encoding="utf-8"?> 
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  3.     android:orientation="horizontal" 
  4.     android:layout_width="fill_parent" 
  5.     android:layout_height="fill_parent" 
  6.     > 
  7. <ImageView   
  8.     android:layout_width="wrap_content"   
  9.     android:layout_height="wrap_content"   
  10.     android:id="@+id/iv" 
  11.     />   
  12.    <LinearLayout 
  13.         android:orientation="vertical" 
  14.         android:layout_width="wrap_content" 
  15.         android:layout_height="wrap_content" 
  16.         > 
  17.         <TextView    
  18.             android:layout_width="wrap_content"   
  19.             android:layout_height="wrap_content"   
  20.             android:textSize="20sp" 
  21.             android:id="@+id/bigtv" 
  22.             /> 
  23.         <TextView    
  24.             android:layout_width="wrap_content"   
  25.             android:layout_height="wrap_content"   
  26.             android:textSize="10sp" 
  27.             android:id="@+id/smalltv" 
  28.             /> 
  29.     </LinearLayout> 
  30. <Button    
  31.     android:layout_width="wrap_content"   
  32.     android:layout_height="wrap_content"   
  33.      android:text="button" 
  34.     android:id="@+id/btn" 
  35.     /> 
  36. <CheckBox    
  37.    android:layout_width="wrap_content"   
  38.    android:layout_height="wrap_content"   
  39.    android:id="@+id/cb" 
  40.    /> 
  41. </LinearLayout> 

 


修改源碼:MainActivity.java:

 

  1. public class MainActivity extends Activity {  
  2.     private SimpleAdapter adapter;// 聲明適配器對象  
  3.     private ListView listView; // 聲明列表視圖對象  
  4.     private List<Map<String, Object>> list;// 聲明列表容器  
  5.     public static MainActivity ma;  
  6.     @Override 
  7.     public void onCreate(Bundle savedInstanceState) {  
  8.         super.onCreate(savedInstanceState);  
  9.         ma = this;  
  10.         // 實例化列表容器  
  11.         list = new ArrayList<Map<String, Object>>();  
  12.         listView = new ListView(this);// 實例化列表視圖  
  13.         // 實例一個列表數據容器  
  14.         Map<String, Object> map = new HashMap<String, Object>();  
  15.         // 往列表容器中添加數據  
  16.         map.put("item1_imageivew", R.drawable.icon);  
  17.         map.put("item1_bigtv", "BIGTV");  
  18.         map.put("item1_smalltv", "SMALLTV");  
  19.         // 將列表數據添加到列表容器中  
  20.         list.add(map);  
  21.         // --使用系統適配器,無法實現組件監聽;  
  22.         // //實例適配器  
  23.         adapter = new SimpleAdapter(this, list, R.layout.main, new String[] {  
  24.                 "item1_imageivew", "item1_bigtv", "item1_smalltv" }, new int[] {  
  25.                 R.id.iv, R.id.bigtv, R.id.smalltv });  
  26.         listView.setAdapter(adapter);  
  27.         // //顯示列表視圖  
  28.         this.setContentView(listView);  
  29.     }  

到此,我們之前要求完成的(圖1)要求的ListView,[對ListView不太熟悉的童鞋自行百度google先學習一下基礎吧]

當然這裡我們只是完成了界面,如果想監聽(圖1)中的按鈕和復選框事件,那麼我們肯定需要自定義一個適配器,那麼下面開始介紹如何實現通用適配器:

創建一個新類,類名:“MySimpleAdapter.java”繼承BaseAdapter:

 

  1. /**  
  2.  *   
  3.  */ 
  4. package com.himi;  
  5. import java.util.List;  
  6. import java.util.Map;  
  7. import android.app.AlertDialog;  
  8. import android.content.Context;  
  9. import android.view.LayoutInflater;  
  10. import android.view.View;  
  11. import android.view.ViewGroup;  
  12. import android.widget.BaseAdapter;  
  13. import android.widget.Button;  
  14. import android.widget.CheckBox;  
  15. import android.widget.CompoundButton;  
  16. import android.widget.ImageView;  
  17. import android.widget.TextView;  
  18. import android.widget.CompoundButton.OnCheckedChangeListener;  
  19. /**  
  20.  * @author Himi  
  21.  *   
  22.  */ 
  23. public class MySimpleAdapter extends BaseAdapter {  
  24.     private LayoutInflater mInflater;  
  25.     private List<Map<String, Object>> list;  
  26.     private int layoutID;  
  27.     private String flag[];  
  28.     private int ItemIDs[];  
  29.     public MySimpleAdapter(Context context, List<Map<String, Object>> list,  
  30.             int layoutID, String flag[], int ItemIDs[]) {  
  31.         this.mInflater = LayoutInflater.from(context);  
  32.         this.list = list;  
  33.         this.layoutID = layoutID;  
  34.         this.flag = flag;  
  35.         this.ItemIDs = ItemIDs;  
  36.     }  
  37.     @Override 
  38.     public int getCount() {  
  39.         // TODO Auto-generated method stub  
  40.         return list.size();  
  41.     }  
  42.     @Override 
  43.     public Object getItem(int arg0) {  
  44.         // TODO Auto-generated method stub  
  45.         return 0;  
  46.     }  
  47.     @Override 
  48.     public long getItemId(int arg0) {  
  49.         // TODO Auto-generated method stub  
  50.         return 0;  
  51.     }  
  52.     @Override 
  53.     public View getView(int position, View convertView, ViewGroup parent) {  
  54.         convertView = mInflater.inflate(layoutID, null);  
  55.         for (int i = 0; i < flag.length; i++) {//備注1  
  56.             if (convertView.findViewById(ItemIDs[i]) instanceof ImageView) {  
  57.                 ImageView iv = (ImageView) convertView.findViewById(ItemIDs[i]);  
  58.                 iv.setBackgroundResource((Integer) list.get(position).get(  
  59.                         flag[i]));  
  60.             } else if (convertView.findViewById(ItemIDs[i]) instanceof TextView) {  
  61.                 TextView tv = (TextView) convertView.findViewById(ItemIDs[i]);  
  62.                 tv.setText((String) list.get(position).get(flag[i]));  
  63.             }else{  
  64.                 //...備注2  
  65.             }  
  66.         }  
  67.         addListener(convertView);  
  68.         return convertView;  
  69.     }  
  70. /**  
  71.  * 童鞋們只需要將需要設置監聽事件的組件寫在下面這方法裡就可以啦!  
  72.  * 別的不需要修改!  
  73.  * 備注3  
  74.  */ 
  75.     public void addListener(View convertView) {  
  76.         ((Button)convertView.findViewById(R.id.btn)).setOnClickListener(  
  77.                 new View.OnClickListener() {  
  78.                     @Override 
  79.                     public void onClick(View v) {  
  80.                         new AlertDialog.Builder(MainActivity.ma)  
  81.                         .setTitle("自定義通用SimpleAdapter")  
  82.                         .setMessage("按鈕成功觸發監聽事件!")  
  83.                         .show();  
  84.                     }  
  85.                 });  
  86.         ((CheckBox)convertView.findViewById(R.id.cb)).  
  87.         setOnCheckedChangeListener(new OnCheckedChangeListener() {  
  88.             @Override 
  89.             public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {  
  90.                 new AlertDialog.Builder(MainActivity.ma)  
  91.                 .setTitle("自定義通用SimpleAdapter")  
  92.                 .setMessage("CheckBox成功觸發狀態改變監聽事件!")  
  93.                 .show();  
  94.             }  
  95.         });  
  96.     }  


備注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://download.csdn.net/source/3157277

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved