Android之ListView包含多种类型的Item

来源:互联网 发布:软件资格水平考试 编辑:程序博客网 时间:2024/06/04 18:38

一般情况下,ListView中的Item的类型的都是相同的,即每个Item的布局都调用的同一个XML。但是我们现在的需求需要ListView包含多种类型,需要如何实现呢?

是的,就是覆写Adapter的getItemViewType(int position)和get ViewTypeCount()方法。

getItemViewType(int position)代表第position个Item的类型是什么,返回值为 int值。并且在getView中调用这个方法,并且根据返回值值的类型加载不同的布局。

get ViewTypeCount()表示Item类型种类的个数。


这里我们实现3中类型的Item。

首先构建3个ViewHolder类型,然后根据getItemViewType的返回值,在getView中加载不同ViewHolder。

这里不知道ViewHolder的同学,请看Android之ListView性能优化 里面讲解了通过convertView以及ViewHolder来优化ListView性能


package com.example.listviewbaseadapter;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import android.os.Bundle;import android.app.Activity;import android.content.Context;import android.util.Log;import android.view.LayoutInflater;import android.view.View;import android.view.View.OnClickListener;import android.view.ViewGroup;import android.widget.AdapterView;import android.widget.AdapterView.OnItemClickListener;import android.widget.BaseAdapter;import android.widget.Button;import android.widget.HorizontalScrollView;import android.widget.ImageView;import android.widget.ListView;import android.widget.TextView;public class BaseAdapterListView extends Activity {private ListView listview;private List<Map<String, Object>> data; // List集合中的对象是一个Map对象,而这个Map对象的键是String类型,值是Object类型public final static int Type_1 = 0;public final static int Type_2 = 1;public final static int Type_3 = 2;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_base_adapter_list_view);listview = (ListView) findViewById(R.id.lv);listview.setOnItemClickListener(new OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) {// TODO Auto-generated method stubLog.d("base", "item has worked");}});// 将要绑定的数据赋给datadata = getData();MyAdapter adapter = new MyAdapter(this);listview.setAdapter(adapter);}private List<Map<String, Object>> getData() {// TODO Auto-generated method stubList<Map<String, Object>> list = new ArrayList<Map<String, Object>>();Map<String, Object> map;// 遍历for (int x = 0; x < 50; x++) {map = new HashMap<String, Object>();map.put("button", "button" + x);map.put("text1", "优化ListView" + x);map.put("text2", "重写BaseAdapter" + x);list.add(map);}Log.v("myu", "list count="+list.size());return list;}// 通过ViewHolder静态类结合缓存convertView优化ListView性能// 使用 ViewHolder 的好处是缓存了显示数据的视图(View),加快了 UI 的响应速度。static class ViewHolder1 {public Button btn;public TextView text1;public TextView text2;}static class ViewHolder2 {public TextView text3;}static class ViewHolder3 {public ImageView imageView3;}public class MyAdapter extends BaseAdapter {private LayoutInflater mInflater = null;private MyAdapter(Context context) {// 根据context上下文加载布局mInflater = LayoutInflater.from(context);}@Overridepublic int getCount() {Log.v("myu", "getCount()");// TODO Auto-generated method stub// 在此适配器中所代表的数据集中的条目数// 系统首先调用getCount()函数,根据他的返回值得到listView的长度,然后根据这个长度,调用getView()逐一绘制每一行// 如果你的getCount()返回值是0的话,列表将不显示同样return 1,就只显示一行。return data.size();}@Overridepublic Object getItem(int position) {Log.v("myu", "getItem(" +position +")");// TODO Auto-generated method stub// 获取数据集中与指定索引对应的数据项return position;}@Overridepublic long getItemId(int position) {Log.v("myu", "getItemId(" +position +")");// TODO Auto-generated method stub// 获取在列表中与指定索引对应的行idreturn position;}@Overridepublic int getItemViewType(int position) {// TODO Auto-generated method stubLog.v("myu", "getItemViewType " + position);if (position % 3 == 0) {return Type_1;} else if (position % 3 == 1) {return Type_2;} else {return Type_3;}}@Overridepublic int getViewTypeCount() {Log.v("myu", "getViewTypeCount() ");// TODO Auto-generated method stubreturn 3;}// 获取一个在数据集中指定索引的视图来显示数据@Overridepublic View getView(final int position, View convertView,ViewGroup parent) {Log.v("myu", "getView("+ position+") ");// TODO Auto-generated method stubViewHolder1 holder = null;ViewHolder2 holder2 = null;ViewHolder3 holder3 = null;int type = getItemViewType(position);Log.v("myu", "getView " + position + " " + convertView + " type = "+ type);// 如果缓存convertView为空,则需要创建Viewif (convertView == null) {switch (type) {case Type_1:holder = new ViewHolder1();convertView = mInflater.inflate(R.layout.item, null);holder.btn = (Button) convertView.findViewById(R.id.btn1);holder.btn.setText("button"+position);holder.text1 = (TextView) convertView.findViewById(R.id.text1);holder.text2 = (TextView) convertView.findViewById(R.id.text2);// 将设置好的布局保存到缓存中,并将其设置在Tag里,以便后面方便取出Tag// 绑定ViewHolder对象convertView.setTag(holder);break;case Type_2:holder2 = new ViewHolder2();convertView = mInflater.inflate(R.layout.item2, null);holder2.text3 = (TextView) convertView.findViewById(R.id.text3);holder2.text3.setText(data.get(position).get("text1").toString());convertView.setTag(holder2);break;case Type_3:holder3 = new ViewHolder3();convertView = mInflater.inflate(R.layout.item3, null);holder3.imageView3 = (ImageView) convertView.findViewById(R.id.imageView);convertView.setTag(holder2);break;default:break;}} else {switch (type) {case Type_1:holder = (ViewHolder1) convertView.getTag();// 取出ViewHolder对象/** 设置控件显示的内容,即我们存放在动态数组中的数据 */holder.btn.setText((String) data.get(position).get("button")); // 通过get("button")// 与MAP做KEY对应holder.text1.setText((String) data.get(position).get("text1"));holder.text2.setText((String) data.get(position).get("text2"));holder.btn.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubLog.v("base", "你点击了按钮");data.remove(position); // 移除该itemMyAdapter.this.notifyDataSetChanged(); // 刷新ListView}});break;case Type_2:holder2 = (ViewHolder2) convertView.getTag();holder2.text3.setText(data.get(position).get("text1").toString());break;case Type_3:holder3 = (ViewHolder3) convertView.getTag();break;default:break;}}return convertView;}}}

效果图:



三种类型的Item分别为一个包含Button和两个TextView、一个只包含TextView、一个只包含ImageView  

0 0