在Android的Listview中显示多种视图

看得懂E文的看此文,分析的很透彻:

http://android.amberfog.com/?p=296


1.场景

  在使用ListView时,我们经常遇到需要在一个ListView中显示多种视图的场景,例如:聊天软件的聊天界面中,自己发送的消息在左边显示自己的头像,别人发送的消息在右边显示别人的头像,等等。

2.ListView常用方式
      2.1 ListView常用的Adapter有:ArrayAdapter,SimpleAdapter,CursorAdapter。在android sdk sample的ApiDemo工程中有详细的使用方法。

      2.2 当我们需要在ListView的视图中展示复杂的数据和资源,处理复杂的事件时,我们可以继承BaseAdapter,重写BaseAdapter中的方法来达到目的,主要是getView(int position, View convertView, ViewGroup parent)方法。在android sdk sample的ApiDemo工程中有详细的使用方法。

      2.3 当我们需要在ListView中显示多种视图时,仍然使用继承BaseAdapter的方式,要注意的是getItemViewType(int position)和getViewTypeCount()这两个方法。

3.ListView中显示多种视图的实现方式
      3.1 实现步骤
            3.1.1 定义试图类型常量
            我们定义了三种:

[java]  view plain copy
  1. /** 
  2.  * 发送的消息 
  3.  */  
  4. private static final int TYPE_SEND = 0;  
  5. /** 
  6.  * 收到的消息 
  7.  */  
  8. private static final int TYPE_RECEIVE = TYPE_SEND + 1;  
  9. /** 
  10.  * 图片 
  11.  */  
  12. private static final int TYPE_PIC = TYPE_RECEIVE + 1;  

            3.1.2 重写getItemViewType(int position)和getViewTypeCount()方法

[java]  view plain copy
  1. public int getItemViewType(int position) {  
  2.     int type = super.getItemViewType(position);  
  3.     try  
  4.     {  
  5.         type = Integer.parseInt(data.get(position).get("type"));  
  6.     } catch (Exception e)  
  7.     {  
  8.         e.printStackTrace();  
  9.     }  
  10.     System.out.println("getItemViewType::" + position + " is " + type);  
  11.     return type;  
  12. }  
  13.   
  14. public int getViewTypeCount() {  
  15.     System.out.println("getViewTypeCount is " + 3);  
  16.     return 3;  
  17. }  

由getItemViewType返回对应项的自定义视图类型,getViewTypeCount返回视图类型总数。
         注意:getViewTypeCount返回的值必须比视图类型常量值大,以数组来比喻的话,getViewTypeCount返回的是数组的长度,getItemViewType返回的(即3.1.1中定义的常量)就是数组的下标。
            3.1.2 重写getView方法

[java]  view plain copy
  1. public View getView(int position, View convertView, ViewGroup parent) {  
  2.     System.out.println("getView::" + position);  
  3.     int type = TYPE_SEND;  
  4.     try  
  5.     {  
  6.         type = Integer.parseInt(data.get(position).get("type"));  
  7.     } catch (Exception e)  
  8.     {  
  9.         e.printStackTrace();  
  10.     }  
  11.     ViewHolder holder = null;  
  12.     if (convertView == null)  
  13.     {  
  14.         System.out.println("getView::convertView is null");  
  15.         holder = new ViewHolder();  
  16.         switch (type)  
  17.         {  
  18.         case TYPE_SEND:  
  19.             convertView = View.inflate(getBaseContext(),  
  20.                     R.layout.listitem_send, null);  
  21.             holder.text = (TextView) convertView  
  22.                     .findViewById(R.id.message);  
  23.             break;  
  24.         case TYPE_RECEIVE:  
  25.             convertView = View.inflate(getBaseContext(),  
  26.                     R.layout.listitem_receive, null);  
  27.             holder.text = (TextView) convertView  
  28.                     .findViewById(R.id.message);  
  29.             break;  
  30.         case TYPE_PIC:  
  31.             convertView = new ImageView(getBaseContext());  
  32.             ((ImageView) convertView).setImageResource(R.drawable.icon);  
  33.             break;  
  34.         }  
  35.         convertView.setTag(holder);  
  36.     }  
  37.     else  
  38.     {  
  39.         System.out.println("getView::convertView not null");  
  40.         holder = (ViewHolder) convertView.getTag();  
  41.     }  
  42.       
  43.     if (type != TYPE_PIC)  
  44.     {  
  45.         String msg = data.get(position).get("content");  
  46.         holder.text.setText(msg);  
  47.     }  
  48.     return convertView;  
  49. }  

      这一部分和2.2是差不多的,不同的地方在于当convertView为空时,需要根据当前项数据对应的视图类型初始化相应的视图布局。其他像getCount,getItem方法照例重写。
      
     

      3.2 过程分析

        在ListView的父类AbsListView中,有一个变量RecycleBin mRecycler,用来存储某一显示项布局对应的视图。实际存储在 ArrayList<View>[] 中,该数组的长度为getViewTypeCount的返回值。RecycleBin 是AbsListView的一个内部类。
 
当ListView执行 setAdapter方法时,mRecycler会重置,getViewTypeCount方法会被调用。        

        当ListView要显示某一项时,getItemViewType方法被调用,根据返回值在mRecycler搜索得到缓存的视图。这也是为什么getViewTypeCount返回值要比定义的视图类型常量值大的原因,否则会导致数组越界异常。
 
  然后调用getView方法,缓存的视图被传递给getView方法的convertView形参(详细可以参考AbsListView的obtainView方法)。
        当传递进来的convertView形参为null的话,需要根据该项的视图类型,初始化布局。

  最后给显示项填充数据。

下载源码
http://download.youkuaiyun.com/detail/clarketang/3694460


原文:

1.场景

  在使用ListView时,我们经常遇到需要在一个ListView中显示多种视图的场景,例如:聊天软件的聊天界面中,自己发送的消息在左边显示自己的头像,别人发送的消息在右边显示别人的头像,等等。

2.ListView常用方式
      2.1 ListView常用的Adapter有:ArrayAdapter,SimpleAdapter,CursorAdapter。在android sdk sample的ApiDemo工程中有详细的使用方法。

      2.2 当我们需要在ListView的视图中展示复杂的数据和资源,处理复杂的事件时,我们可以继承BaseAdapter,重写BaseAdapter中的方法来达到目的,主要是getView(int position, View convertView, ViewGroup parent)方法。在android sdk sample的ApiDemo工程中有详细的使用方法。

      2.3 当我们需要在ListView中显示多种视图时,仍然使用继承BaseAdapter的方式,要注意的是getItemViewType(int position)和getViewTypeCount()这两个方法。

3.ListView中显示多种视图的实现方式
      3.1 实现步骤
            3.1.1 定义试图类型常量
            我们定义了三种:

[java]  view plain copy
  1. /** 
  2.  * 发送的消息 
  3.  */  
  4. private static final int TYPE_SEND = 0;  
  5. /** 
  6.  * 收到的消息 
  7.  */  
  8. private static final int TYPE_RECEIVE = TYPE_SEND + 1;  
  9. /** 
  10.  * 图片 
  11.  */  
  12. private static final int TYPE_PIC = TYPE_RECEIVE + 1;  

            3.1.2 重写getItemViewType(int position)和getViewTypeCount()方法

[java]  view plain copy
  1. public int getItemViewType(int position) {  
  2.     int type = super.getItemViewType(position);  
  3.     try  
  4.     {  
  5.         type = Integer.parseInt(data.get(position).get("type"));  
  6.     } catch (Exception e)  
  7.     {  
  8.         e.printStackTrace();  
  9.     }  
  10.     System.out.println("getItemViewType::" + position + " is " + type);  
  11.     return type;  
  12. }  
  13.   
  14. public int getViewTypeCount() {  
  15.     System.out.println("getViewTypeCount is " + 3);  
  16.     return 3;  
  17. }  

由getItemViewType返回对应项的自定义视图类型,getViewTypeCount返回视图类型总数。
         注意:getViewTypeCount返回的值必须比视图类型常量值大,以数组来比喻的话,getViewTypeCount返回的是数组的长度,getItemViewType返回的(即3.1.1中定义的常量)就是数组的下标。
            3.1.2 重写getView方法

[java]  view plain copy
  1. public View getView(int position, View convertView, ViewGroup parent) {  
  2.     System.out.println("getView::" + position);  
  3.     int type = TYPE_SEND;  
  4.     try  
  5.     {  
  6.         type = Integer.parseInt(data.get(position).get("type"));  
  7.     } catch (Exception e)  
  8.     {  
  9.         e.printStackTrace();  
  10.     }  
  11.     ViewHolder holder = null;  
  12.     if (convertView == null)  
  13.     {  
  14.         System.out.println("getView::convertView is null");  
  15.         holder = new ViewHolder();  
  16.         switch (type)  
  17.         {  
  18.         case TYPE_SEND:  
  19.             convertView = View.inflate(getBaseContext(),  
  20.                     R.layout.listitem_send, null);  
  21.             holder.text = (TextView) convertView  
  22.                     .findViewById(R.id.message);  
  23.             break;  
  24.         case TYPE_RECEIVE:  
  25.             convertView = View.inflate(getBaseContext(),  
  26.                     R.layout.listitem_receive, null);  
  27.             holder.text = (TextView) convertView  
  28.                     .findViewById(R.id.message);  
  29.             break;  
  30.         case TYPE_PIC:  
  31.             convertView = new ImageView(getBaseContext());  
  32.             ((ImageView) convertView).setImageResource(R.drawable.icon);  
  33.             break;  
  34.         }  
  35.         convertView.setTag(holder);  
  36.     }  
  37.     else  
  38.     {  
  39.         System.out.println("getView::convertView not null");  
  40.         holder = (ViewHolder) convertView.getTag();  
  41.     }  
  42.       
  43.     if (type != TYPE_PIC)  
  44.     {  
  45.         String msg = data.get(position).get("content");  
  46.         holder.text.setText(msg);  
  47.     }  
  48.     return convertView;  
  49. }  

      这一部分和2.2是差不多的,不同的地方在于当convertView为空时,需要根据当前项数据对应的视图类型初始化相应的视图布局。其他像getCount,getItem方法照例重写。
      
     

      3.2 过程分析

        在ListView的父类AbsListView中,有一个变量RecycleBin mRecycler,用来存储某一显示项布局对应的视图。实际存储在 ArrayList<View>[] 中,该数组的长度为getViewTypeCount的返回值。RecycleBin 是AbsListView的一个内部类。
 
当ListView执行 setAdapter方法时,mRecycler会重置,getViewTypeCount方法会被调用。        

        当ListView要显示某一项时,getItemViewType方法被调用,根据返回值在mRecycler搜索得到缓存的视图。这也是为什么getViewTypeCount返回值要比定义的视图类型常量值大的原因,否则会导致数组越界异常。
 
  然后调用getView方法,缓存的视图被传递给getView方法的convertView形参(详细可以参考AbsListView的obtainView方法)。
        当传递进来的convertView形参为null的话,需要根据该项的视图类型,初始化布局。

  最后给显示项填充数据。

下载源码
http://download.youkuaiyun.com/detail/clarketang/3694460


原文:http://blog.youkuaiyun.com/clarketang/article/details/6873393



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值