之前介紹了三種adapter:ArrayAdapter<T>、SimpleAdapter和SimpleCursorAdapter。
使用android提供的adapter來繪製列表的話,列表的每一項的顯示都是一樣的。為了實現ListView的單雙行不同顏色顯示,需要自定義adapter的子類。adapter的常用子類有BaseAdapter、ArrayAdapter、SimpleAdapter等,下面介紹自定義BaseAdapter和ArrayAdapter的實現。
1.自定義BaseAdapter
效果圖如下:
![](https://i.iter01.com/images/026ade57f8153a4d4ad2398528789dc20750eb9fb16d61e0d2cdc9bedb0ea728.png)
在上一篇《ListView(1)——各種Adapter的使用》的基礎上,為了實現ListView的單雙行不同顏色顯示,需要自定義adapter的子類,而activity_main.xml檔案和list_item.xml檔案都不需要更改,MainActivity.java程式碼修改如下:
-
@Override
-
protected void onCreate(Bundle savedInstanceState) {
-
super.onCreate(savedInstanceState);
-
setContentView(R.layout.activity_main);
-
-
-
int[] images = new int[] { R.drawable.item_img_a,
-
R.drawable.item_img_b, R.drawable.item_img_c,
-
R.drawable.item_img_d, R.drawable.item_img_e };
-
-
List<HashMap<String, Object>> data = new ArrayList<HashMap<String, Object>>();
-
for (int i = 0; i < 5; i++) {
-
HashMap<String, Object> map = new HashMap<String, Object>();
-
map.put("ItemImage", images[i]);
-
map.put("ItemTitle", "This is Title " + i);
-
map.put("ItemText", "This is text " + i);
-
data.add(map);
-
}
-
-
-
ListView listView = (ListView) findViewById(R.id.list);
-
-
MyBaseAdapter adapter = new MyBaseAdapter(MainActivity.this, data);
-
listView.setAdapter(adapter);
-
}
下面我們實現自定義的MyBaseAdapter類。MyBaseAdapter類繼承自BaseAdapter類,BaseAdapter為抽象類,繼承它需要實現如下方法,因此具有較高的靈活性。
-
public class MyBaseAdapter extends BaseAdapter {
-
-
@Override
-
public int getCount() {
-
-
return 0;
-
}
-
-
@Override
-
public Object getItem(int arg0) {
-
-
return null;
-
}
-
-
@Override
-
public long getItemId(int position) {
-
-
return 0;
-
}
-
-
@Override
-
public View getView(int position, View convertView, ViewGroup parent) {
-
-
return null;
-
}
-
-
}
ListView在繪製時首先會呼叫getCount()方法得到繪製次數,然後通過getView()方法一層一層進行繪製,所以我們可以在getView()方法中根據position(當前繪製的ID)來的修改繪製內容。而getItem()和getItemId()則在需要處理和取得Adapter中的資料時呼叫。
-
public class MyBaseAdapter extends BaseAdapter {
-
private int[] colors = new int[] { 0xff3cb371, 0xffa0a0a0 };
-
private Context mContext;
-
private List<HashMap<String, Object>> dataList;
-
-
public MyBaseAdapter(Context context, List<HashMap<String, Object>> dataList) {
-
this.mContext = context;
-
this.dataList = dataList;
-
}
-
-
@Override
-
public int getCount() {
-
return dataList.size();
-
}
-
-
@Override
-
public HashMap<String, Object> getItem(int position) {
-
return dataList.get(position);
-
}
-
-
@Override
-
public long getItemId(int position) {
-
return position;
-
}
-
-
@Override
-
public View getView(int position, View convertView, ViewGroup parent) {
-
ViewHolder holder = null;
-
if (convertView == null) {
-
holder = new ViewHolder();
-
convertView = LayoutInflater.from(mContext).inflate(
-
R.layout.list_item, null);
-
holder.image = (ImageView) convertView.findViewById(R.id.ItemImage);
-
holder.title = (TextView) convertView.findViewById(R.id.ItemTitle);
-
holder.text = (TextView) convertView.findViewById(R.id.ItemText);
-
-
-
convertView.setTag(holder);
-
} else {
-
holder = (ViewHolder) convertView.getTag();
-
}
-
-
-
holder.image.setImageResource((Integer) getItem(position).get(
-
"ItemImage"));
-
holder.title.setText((String) getItem(position).get("ItemTitle"));
-
holder.text.setText((String) getItem(position).get("ItemText"));
-
-
int colorPos = position % colors.length;
-
convertView.setBackgroundColor(colors[colorPos]);
-
-
return convertView;
-
}
-
-
-
-
-
final class ViewHolder {
-
ImageView image;
-
TextView title;
-
TextView text;
-
}
-
}
getView()方法用來獲得繪製每個item的View物件,如果每次getView()被執行都new出一個View物件,長此以往會產生很大的消耗,特別當item中還有Bitmap等,甚至會造成OOM的錯誤導致程式崩潰。從上面的程式碼可以看到getView()有一個convertView引數,這個引數用來快取View物件。當ListView滑動的過程中,會有item被滑出螢幕而不再被使用,這時候Android會回收這個item的view,這個view也就是這裡的convertView。這樣如果convertView不為null,就不用new出一個新的View物件,只用往convertView中填充新的item,這樣就省去了new
View的大量開銷。
在上面的程式碼中,在快取convertView減少new View開銷的同時,通過setTag()方法將資料結構ViewHolder繫結到convertView,從而利用ViewHolder儲存convertView中控制元件物件的引用,這樣避免每次呼叫findViewById()方法。
2.自定義ArrayAdapter<T>
在開發中需要將物件顯示在listview中,這時候使用ArrayAdapter<T>來顯示指定物件型別。下面自定義ArrayAdapter<T>實現上一節中自定義BaseAdapter實現的同樣的效果,首先定義要顯示的物件,程式碼如下ItemBean.java。
-
public class ItemBean {
-
private int image;
-
private String title;
-
private String text;
-
-
public ItemBean(int image, String title, String text) {
-
this.image = image;
-
this.title = title;
-
this.text = text;
-
}
-
-
public int getImage() {
-
return image;
-
}
-
-
public String getTitle() {
-
return title;
-
}
-
-
public String getText() {
-
return text;
-
}
-
}
和上一節一樣,為了實現ListView的單雙行不同顏色顯示,需要自定義adapter的子類,而activity_main.xml檔案和list_item.xml檔案都不需要更改,MainActivity.java程式碼修改如下:
-
@Override
-
protected void onCreate(Bundle savedInstanceState) {
-
super.onCreate(savedInstanceState);
-
setContentView(R.layout.activity_main);
-
-
-
int[] images = new int[] { R.drawable.item_img_a,
-
R.drawable.item_img_b, R.drawable.item_img_c,
-
R.drawable.item_img_d, R.drawable.item_img_e };
-
-
ArrayList<ItemBean> data = new ArrayList<ItemBean>();
-
for (int i = 0; i < 5; i++) {
-
ItemBean itemBean = new ItemBean(images[i], "This is Title " + i,
-
"This is text " + i);
-
data.add(itemBean);
-
}
-
-
-
ListView listView = (ListView) findViewById(R.id.list);
-
-
MyArrayAdapter adapter = new MyArrayAdapter(MainActivity.this,
-
R.layout.list_item, data);
-
listView.setAdapter(adapter);
-
}
接下來自定義繼承自ArrayAdapter<ItemBean>的MyArrayAdapter類,繼承ArrayAdapter<ItemBean>只需要重寫getView()方法就可以實現與上一節相同的效果,並且不用儲存List<ItemBean>物件引用。
-
public class MyArrayAdapter extends ArrayAdapter<ItemBean> {
-
private int[] colors = new int[] { 0xff3cb371, 0xffa0a0a0 };
-
private Context mContext;
-
private int resource;
-
-
public MyArrayAdapter(Context context, int resource, List<ItemBean> data) {
-
super(context, resource, data);
-
this.mContext = context;
-
this.resource = resource;
-
}
-
-
@Override
-
public View getView(int position, View convertView, ViewGroup parent) {
-
ViewHolder holder = null;
-
if (convertView == null) {
-
holder = new ViewHolder();
-
convertView = LayoutInflater.from(mContext).inflate(resource, null);
-
holder.image = (ImageView) convertView.findViewById(R.id.ItemImage);
-
holder.title = (TextView) convertView.findViewById(R.id.ItemTitle);
-
holder.text = (TextView) convertView.findViewById(R.id.ItemText);
-
-
-
convertView.setTag(holder);
-
} else {
-
holder = (ViewHolder) convertView.getTag();
-
}
-
-
-
holder.image.setImageResource(getItem(position).getImage());
-
holder.title.setText(getItem(position).getTitle());
-
holder.text.setText(getItem(position).getText());
-
-
int colorPos = position % colors.length;
-
convertView.setBackgroundColor(colors[colorPos]);
-
-
return convertView;
-
}
-
-
-
-
-
final class ViewHolder {
-
ImageView image;
-
TextView title;
-
TextView text;
-
}
-
}
參考文章:
http://www.open-open.com/lib/view/open1339485728006.html