編輯: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:
- <?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:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:id="@+id/iv"
- />
- <LinearLayout
- android:orientation="vertical"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- >
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textSize="20sp"
- android:id="@+id/bigtv"
- />
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textSize="10sp"
- android:id="@+id/smalltv"
- />
- </LinearLayout>
- <Button
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="button"
- android:id="@+id/btn"
- />
- <CheckBox
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:id="@+id/cb"
- />
- </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;
- /**
- * @author Himi
- *
- */
- 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"
這裡也提醒一下開發游戲的童鞋們,很多游戲開發者認為開發游戲不用去學習系統組件的使用,不用去沾染xml、布局啥的,其實這麼想的童鞋們你們就大錯特錯了,Android之所以能這麼火,其組件的美觀占了很重的份量,這麼美的組件不用豈不是很浪費!!希望童鞋們對組件不熟悉的游戲開發者都要去學習學習下組件的使用!
源碼下載:http://download.csdn.net/source/3157277
說起在android上要實現類似Launch的抽屜效果,大家一定首先會想起SlidingDrawer。SlidingDrawer是android官方控件之一,但是
Android提供了許多方法來控制播放的音頻/視頻文件和流。其中該方法是通過一類稱為MediaPlayer。Android是提供MediaPlayer類訪問內置的媒體播放
Android應用程序可以在許多不同地區的許多設備上運行。為了使應用程序更具交互性,應用程序應該處理以適合應用程序將要使用的語言環境方面的文字,數字,文件等。在本章中,我
公司最近也開始基於android4.0 ICS修改框架了,公司的手機暫時不適合拿回家測試,也沒有kernel的權限。從個人的角度看,我手上現在有兩部手機,一部是H