ListView(2)——自定义Adapter

  • Post author:
  • Post category:其他




之前介绍了三种


adapter:


ArrayAdapter<T>




SimpleAdapter和SimpleCursorAdapter。




使用android提供的

adapter来绘制列表的话,列表的每一项的显示都是一样的。为了实现


ListView的单双行不同颜色显示,需要自定义

adapter的子类。






adapter的常用子类有BaseAdapter、


ArrayAdapter、

SimpleAdapter等,下面介绍自定义

BaseAdapter和


ArrayAdapter的实现。

































1.自定义

BaseAdapter






















效果图如下:







































在上一篇

《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);

	// 图片资源的ID
	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);
	}

	// 绑定XML中的ListView,作为Item的容器
	ListView listView = (ListView) findViewById(R.id.list);

	MyBaseAdapter adapter = new MyBaseAdapter(MainActivity.this, data);
	listView.setAdapter(adapter);
}

















下面我们实现自定义的My

BaseAdapter类。

My


BaseAdapter类继承自

BaseAdapter类,

BaseAdapter为抽象类,继承它需要实现如下方法,因此具有较高的灵活性。




















public class MyBaseAdapter extends BaseAdapter {

	@Override
	public int getCount() {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public Object getItem(int arg0) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public long getItemId(int position) {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		// TODO Auto-generated method stub
		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);

			// 将holder绑定到convertView
			convertView.setTag(holder);
		} else {
			holder = (ViewHolder) convertView.getTag();
		}

		// 向ViewHolder中填入的数据
		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;
	}

	/**
	 * ViewHolder类用以储存item中控件的引用
	 */
	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);

	// 图片资源的ID
	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);
	}

	// 绑定XML中的ListView,作为Item的容器
	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);

			// 将holder绑定到convertView
			convertView.setTag(holder);
		} else {
			holder = (ViewHolder) convertView.getTag();
		}

		// 向ViewHolder中填入的数据
		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;
	}

	/**
	 * ViewHolder类用以储存item中控件的引用
	 */
	final class ViewHolder {
		ImageView image;
		TextView title;
		TextView text;
	}
}


参考文章:



http://www.open-open.com/lib/view/open1339485728006.html
















































版权声明:本文为u011500793原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。