实现的界面效果如下图所示,没有可以进行布局上的调整,所以看起来丑一点。
上图在一个ListView中显示了两种不同的ItemView,主要是使用BaseAdapter中的getItemViewType()方法,以及getViewTypeCount()方法实现的。
下面来说说详细的实现步骤:
1. 跟以前使用自定义adapter时一样,都需要编写itemView的xml布局文件。只不过在此例中需要编写两个xml布局文件,分别对应了两个不同的itemView。两个xml文件的代码如下:
布局1
布局2
2.自定义一个Adapter类继承自BaseAdapter。并实现 getItemViewType()方法,以及getViewTypeCount()方法。顾名思义,getItemViewType()方法是用来获取当前需要绘制的itemView的类型,getViewTypeCount()方法是用来获取不同的itemview的种类数,即总共有多少种不同种类的itemView。
自定义适配器的代码如下:
/** * Created by Kent on 2014/12/12. */public class MyAdapter extends BaseAdapter { private Context mContext = null;//上下文 private LayoutInflater mInflater = null; private List首先要说一下listview的绘制原理,在listview进行绘制的时候,首先要调用getCount()方法来确定listview的item个数,然后在绘制每个item的时候调用getView方法来进行绘制,而getItem和getItemId是在listview响应用户操作时间时候进行调用的。mData = null;//要显示的数据 public MyAdapter(Context context, List data){ this.mInflater = LayoutInflater.from(context); this.mData = data; } //添加一个新的Item,并通知listview进行显示刷新 public void addItem(BaseItem newItem){ this.mData.add(newItem); this.notifyDataSetChanged(); } @Override public int getItemViewType(int position) { return mData.get(position).getItem_type(); } @Override public int getViewTypeCount() { return ItemType.ITEM_TYPE_MAX_COUNT; } @Override public int getCount() { if(mData == null){ return 0; } return this.mData.size(); } @Override public Object getItem(int i) { return mData.get(i); } @Override public long getItemId(int i) { return i; } @Override public View getView(int position, View convertView, ViewGroup viewGroup) { View viewItem1 = null; View viewItem2 = null; int itemType = this.getItemViewType(position); if(itemType == ViewHolder1.ITEM_VIEW_TYPE_1){ //第一种item ViewHolder1 viewHolder1 = null; if(convertView == null){ //没有缓存过 viewHolder1 = new ViewHolder1(); viewItem1 = this.mInflater.inflate(R.layout.list_view_item_1, null, false); viewHolder1.textView = (TextView)viewItem1.findViewById(R.id. main_activity_list_view_item_1_textview); viewHolder1.imageView = (ImageView)viewItem1.findViewById(R.id. main_activity_list_view_item_1_imageview); viewItem1.setTag(viewHolder1); convertView = viewItem1; }else{ viewHolder1 = (ViewHolder1)convertView.getTag(); } viewHolder1.textView.setText(((ItemBean1) mData.get(position)).getName()); viewHolder1.imageView.setBackgroundResource(R.drawable.ic_launcher); }else if(itemType == ViewHolder2.ITEM_VIEW_TYPE_2){ //第二种item ViewHolder2 viewHolder2 = null; if(convertView == null){ //没有缓存过 viewHolder2 = new ViewHolder2(); viewItem2 = this.mInflater.inflate(R.layout.list_view_item_2, null, false); viewHolder2.textView1 = (TextView)viewItem2.findViewById(R.id. main_activity_list_view_item_2_textview); viewHolder2.textView2 = (TextView)viewItem2.findViewById(R.id. main_activity_list_view_item_2_textview_2); viewItem2.setTag(viewHolder2); convertView = viewItem2; }else{ viewHolder2 = (ViewHolder2)convertView.getTag(); } viewHolder2.textView1.setText(((ItemBean2)mData.get(position)).getName()); viewHolder2.textView2.setText(((ItemBean2)mData.get(position)).getAddress()); } return convertView; }}
这里着重介绍一下getView()方法,这个方法是在绘制每个item时进行调用的,它返回一个View对象,而此View就是需要绘制的View。
public View getView(int position, View convertView, ViewGroup viewGroup) :其中position参数为当前绘制的item的位置,convertView参数为当前要绘制的View,这个参数主要用来缓存,viewGroup参数是当前view的父控件。
关于 getItemViewType()方法,以及getViewTypeCount()方法将在稍后进行讨论。
3. listview数据源:
通常listview里面的数据是来源于一个list集合,而list集合中的元素是Map类型的数据。即:List<> 两个继承自它的子类: 首先来看下getItemViewType()方法; 再来看看getViewTypeCount()方法: 最后来看看最重要的getView()方法: 这个方法使用了ViewHolder进行itemView的缓存。有关内容在此不做解释 源码下载地址:http://download.csdn.net/detail/hhzz1504042001/8262015/** * Created by Kent on 2014/12/15. */public class BaseItem { private int item_type = 0; public BaseItem(int item_type) { this.item_type = item_type; } public int getItem_type() { return item_type; } public void setItem_type(int item_type) { this.item_type = item_type; }}
由于每个Item都需要一个type类型的变量来标识当前Item的种类,所以定义了一个基类:BaseItem类,它只包含一个item_type的属性,用来标识item的种类。 /** * Created by Kent on 2014/12/15. */public class ItemBean1 extends BaseItem{ private String name = null; private String imagePath = null; public ItemBean1(int item_type, String name, String imagePath) { super(item_type); this.name = name; this.imagePath = imagePath; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getImagePath() { return imagePath; } public void setImagePath(String imagePath) { this.imagePath = imagePath; } public int getItemType(){ return super.getItem_type(); } public void setItemType(int itemType){ super.setItem_type(itemType); }}
4. MainActivity中的代码: public class MainActivity extends Activity { private ListView listView = null; //适配器 private MyAdapter myAdapter = null; //数据 private List
5. ViewHolder,用于ItemView的缓存优化: /** * Created by Kent on 2014/12/12. */public final class ViewHolder1 { public static final int ITEM_VIEW_TYPE_1 = 0; public TextView textView = null; public ImageView imageView = null;}
/** * Created by Kent on 2014/12/12. */public final class ViewHolder2 { public static final int ITEM_VIEW_TYPE_2 = 1; public TextView textView1 = null; public TextView textView2 = null;}
/** * Created by Kent on 2014/12/15. */public class ItemType { public static final int ITEM_TYPE_MAX_COUNT = 2;}
6. 实现不同item类型的显示; public int getItemViewType(int position) { return mData.get(position).getItem_type(); }
这个方法返回了当前要绘制的ItemView的类型,类型数据存储在listView的数据源List中的每个bean的itemType属性中。 public int getViewTypeCount() { return ItemType.ITEM_TYPE_MAX_COUNT; }
这个方法返回了不同Item的种类个数。 public View getView(int position, View convertView, ViewGroup viewGroup) { View viewItem1 = null; View viewItem2 = null; int itemType = this.getItemViewType(position); if(itemType == ViewHolder1.ITEM_VIEW_TYPE_1){ //第一种item ViewHolder1 viewHolder1 = null; if(convertView == null){ //没有缓存过 viewHolder1 = new ViewHolder1(); viewItem1 = this.mInflater.inflate(R.layout.list_view_item_1, null, false); viewHolder1.textView = (TextView)viewItem1.findViewById(R.id. main_activity_list_view_item_1_textview); viewHolder1.imageView = (ImageView)viewItem1.findViewById(R.id. main_activity_list_view_item_1_imageview); viewItem1.setTag(viewHolder1); convertView = viewItem1; }else{ viewHolder1 = (ViewHolder1)convertView.getTag(); } viewHolder1.textView.setText(((ItemBean1) mData.get(position)).getName()); viewHolder1.imageView.setBackgroundResource(R.drawable.ic_launcher); }else if(itemType == ViewHolder2.ITEM_VIEW_TYPE_2){ //第二种item ViewHolder2 viewHolder2 = null; if(convertView == null){ //没有缓存过 viewHolder2 = new ViewHolder2(); viewItem2 = this.mInflater.inflate(R.layout.list_view_item_2, null, false); viewHolder2.textView1 = (TextView)viewItem2.findViewById(R.id. main_activity_list_view_item_2_textview); viewHolder2.textView2 = (TextView)viewItem2.findViewById(R.id. main_activity_list_view_item_2_textview_2); viewItem2.setTag(viewHolder2); convertView = viewItem2; }else{ viewHolder2 = (ViewHolder2)convertView.getTag(); } viewHolder2.textView1.setText(((ItemBean2)mData.get(position)).getName()); viewHolder2.textView2.setText(((ItemBean2)mData.get(position)).getAddress()); } return convertView; }
前面已经说过了,getView是在每个Item进行绘制的时候进行调用的,那么想要进行不同类型Item的显示,在这个方法中根据item的类型进行不同的绘制就可以了。 int itemType = this.getItemViewType(position);
获取到当前要绘制的Item的种类。然后根据不同的种类进行不同的布局导入。 viewItem1 = this.mInflater.inflate(R.layout.list_view_item_1, null, false);
联系客服