在上次的「ListView與Adapter之一」中,有說到ArrayAdapter並不適用於自訂(Custom)ListView的場合,所以改用SimpleAdapter。但後來在網路上找到另幾則範例和教學,事實上如果透過改寫(Override)ArrayAdapter中的getView方法也是可以達成自訂ListView的目的。
先看一下getView方法的定義(在介面Adapter中):
getView(int position, View convertView, ViewGroup parent)
Get a View that displays the data at the specified position in the data set.
getView回傳的是一個View物件,回傳的是每一列的要顯示資料的樣子。position指的是引入Adapter的資料數組的位置,convertView指的是轉換過的樣子,parent指的是每個項目視圖上層包含的容器(Container)。有興趣研究可以開啟ArrayAdapter的原始碼來看(事實上它用了另一個方法接在裡面,叫createViewFromResource,看名稱就知這個方法在作什麼的)
除了getView是需要了解的之外,還有一個需要先了解的LayoutInflater類別,Inflater在的,如果你夠宅宅到爆的話,應該知道"充氣娃娃"的英文有一種唸法叫"Inflatable dolls"…所以暫時叫它"充氣"或"膨脹"。
LayoutInflater的用途是:
This class is used to instantiate layout XML file into its corresponding View objects.
所以是可以解析layout的XML檔,然後生成視圖物件,這個過程叫"充氣"。這和findViewById()的功能有點類似,只不過LayoutInflater是解析整個layout的xml,而findViewById()只是解析某個已經設定進來的layout的XML檔中的特定組件。
LayoutInflater不能直接使用,需要透過getLayoutInflater()或getSystemService(String)方法取得目前已掛在正在運作的設備和上下文的實體。(這一段純翻譯官方說明,代表它早就藏在你的系統中)。在Activity中用getLayoutInflater()是最直接、方便、快速的方法。
回到我們的主題中,在getView中使用LayoutInflater的目的,是要把自訂給每一列項目的layout的那個XML檔案解析成一個視圖。這要透過LayoutInflater中的inflate方法(回傳為View),定義如下(註:inflate有多型,這只是其中我們要用的那種):
inflate(int resource, ViewGroup root, boolean attachToRoot)
Inflate a new view hierarchy from the specified xml resource.
以上的知識就可以開始進行getView的改寫,要寫出繼承自ArrayAdapter的MyCustomAdapter,這裡一樣先用內建的simple_list_item_2當每一列的視圖:
-
public class MyCustomAdapter extends ArrayAdapter<String> {
-
-
public MyCustomAdapter(Context context, int textViewResourceId,
-
String[] objects) {
-
super(context, textViewResourceId, objects);
-
-
}
-
-
@Override
-
public View getView(int position, View convertView, ViewGroup parent) {
-
-
LayoutInflater inflater = getLayoutInflater();
-
View row = inflater.inflate(android.R.layout.simple_list_item_2,
-
parent, false);
-
-
TextView tv1 = (TextView) row.findViewById(android.R.id.text1);
-
tv1.setText(mFoods[position]);
-
TextView tv2 = (TextView) row.findViewById(android.R.id.text2);
-
tv2.setText(mPlaces[position]);
-
-
return row;
-
}
-
}
下面和之前的教學一樣,設定ListActivity用我們寫出來的MyCustomAdapter:
-
public void onCreate(Bundle savedInstanceState) {
-
super.onCreate(savedInstanceState);
-
-
// ListActivity設定adapter
-
setListAdapter(new MyCustomAdapter(this,
-
android.R.layout.simple_list_item_2, mFoods));
-
-
// 啟用按鍵過濾功能,這兩行都會進行過濾
-
getListView().setTextFilterEnabled(true);
-
}
最後的結果和之前用SimpleAdapter的一樣:
下一步要用自己定義layout的加上圖片在左邊的那一種,MyCustomAdapter的程式碼如下
-
public class MyCustomAdapter extends ArrayAdapter<String> {
-
-
public MyCustomAdapter(Context context, int textViewResourceId,
-
String[] objects) {
-
super(context, textViewResourceId, objects);
-
-
}
-
-
@Override
-
public View getView(int position, View convertView, ViewGroup parent) {
-
-
LayoutInflater inflater = getLayoutInflater();
-
View row = inflater.inflate(R.layout.mylistview2,
-
parent, false);
-
-
TextView tv1 = (TextView) row.findViewById(R.id.textView1);
-
tv1.setText(mFoods[position]);
-
TextView tv2 = (TextView) row.findViewById(R.id.textView2);
-
tv2.setText(mPlaces[position]);
-
TextView tv3 = (TextView) row.findViewById(R.id.textView3);
-
tv3.setText(mRatings[position]);
-
ImageView iv1=(ImageView) row.findViewById(R.id.imageView1);
-
iv1.setImageResource(mPics[position]);
-
-
return row;
-
}
-
}
結果也是和預期的一樣:
結論:
條條大路通羅馬。對於這種改寫ArrayAdapter的方法,或許在很簡單使用的情況(像我範例的這種),反而比SimpleAdapter簡單得多,是好是壞我就不知道了。不過具備這一些改寫的知識,接下來要研究更複雜的BaseAdapter,就會輕鬆得多了。
阅读(1855) | 评论(0) | 转发(0) |