这篇文章的效果也是大家常见的,各种通讯应用的对话列表都是这种方式,像微信、whatsapp、易信、米聊等。我们这篇文章也权当为回忆,形成简单的笔记。这篇文章参考了2009年Google IO中的《TurboChargeYourUI-How to make your AndroidUI fast and efficient》和2010年Google IO中的《The World of List View》。像2009年Google IO的资料还是很前沿的,那会Android开发资料很少,最重要的就是参考google发布的各种资料。

《TurboChargeYourUI-How to make your AndroidUI fast and efficient》介绍了怎样提高listview的性能,优化了listview的加载速度。这里的item使用的是单一布局,能够实现view的重用和回收,那么多种布局文件的怎么办呢,如果再使用上面的方法,view的重用会出现问题,Android使用的BaseAdapter提供了解决多种布局文件的重用方法。

1)重写 getViewTypeCount() – 该方法返回多少个不同的布局

2)重写 getItemViewType(int) – 根据position返回相应的Item

  1. /**
  2. * 比原来的多了getItemViewType和getViewTypeCount这两个方法,
  3. *
  4. * */
  5. public class ChatAdapter extends BaseAdapter {
  6. public static final String KEY = "key";
  7. public static final String VALUE = "value";
  8. public static final int VALUE_TIME_TIP = 0;// 7种不同的布局
  9. public static final int VALUE_LEFT_TEXT = 1;
  10. public static final int VALUE_LEFT_IMAGE = 2;
  11. public static final int VALUE_LEFT_AUDIO = 3;
  12. public static final int VALUE_RIGHT_TEXT = 4;
  13. public static final int VALUE_RIGHT_IMAGE = 5;
  14. public static final int VALUE_RIGHT_AUDIO = 6;
  15. private LayoutInflater mInflater;
  16. private List<Message> myList;
  17. public ChatAdapter(Context context, List<Message> myList) {
  18. this.myList = myList;
  19. mInflater = (LayoutInflater) context
  20. .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  21. }
  22. @Override
  23. public int getCount() {
  24. return myList.size();
  25. }
  26. @Override
  27. public Object getItem(int arg0) {
  28. return myList.get(arg0);
  29. }
  30. @Override
  31. public long getItemId(int arg0) {
  32. return arg0;
  33. }
  34. @Override
  35. public View getView(int position, View convertView, ViewGroup arg2) {
  36. Message msg = myList.get(position);
  37. int type = getItemViewType(position);
  38. ViewHolderTime holderTime = null;
  39. ViewHolderRightText holderRightText = null;
  40. ViewHolderRightImg holderRightImg = null;
  41. ViewHolderRightAudio holderRightAudio = null;
  42. ViewHolderLeftText holderLeftText = null;
  43. ViewHolderLeftImg holderLeftImg = null;
  44. ViewHolderLeftAudio holderLeftAudio = null;
  45. if (convertView == null) {
  46. switch (type) {
  47. case VALUE_TIME_TIP:
  48. holderTime = new ViewHolderTime();
  49. convertView = mInflater.inflate(R.layout.list_item_time_tip,
  50. null);
  51. holderTime.tvTimeTip = (TextView) convertView
  52. .findViewById(R.id.tv_time_tip);
  53. holderTime.tvTimeTip.setText(msg.getValue());
  54. convertView.setTag(holderTime);
  55. break;
  56. // 左边
  57. case VALUE_LEFT_TEXT:
  58. holderLeftText = new ViewHolderLeftText();
  59. convertView = mInflater.inflate(R.layout.list_item_left_text,
  60. null);
  61. holderLeftText.ivLeftIcon = (ImageView) convertView
  62. .findViewById(R.id.iv_icon);
  63. holderLeftText.btnLeftText = (Button) convertView
  64. .findViewById(R.id.btn_left_text);
  65. holderLeftText.btnLeftText.setText(msg.getValue());
  66. convertView.setTag(holderLeftText);
  67. break;
  68. case VALUE_LEFT_IMAGE:
  69. holderLeftImg = new ViewHolderLeftImg();
  70. convertView = mInflater.inflate(R.layout.list_item_left_iamge,
  71. null);
  72. holderLeftImg.ivLeftIcon = (ImageView) convertView
  73. .findViewById(R.id.iv_icon);
  74. holderLeftImg.ivLeftImage = (ImageView) convertView
  75. .findViewById(R.id.iv_left_image);
  76. holderLeftImg.ivLeftImage.setImageResource(R.drawable.test);
  77. convertView.setTag(holderLeftImg);
  78. break;
  79. case VALUE_LEFT_AUDIO:
  80. holderLeftAudio = new ViewHolderLeftAudio();
  81. convertView = mInflater.inflate(R.layout.list_item_left_audio,
  82. null);
  83. holderLeftAudio.ivLeftIcon = (ImageView) convertView
  84. .findViewById(R.id.iv_icon);
  85. holderLeftAudio.btnLeftAudio = (Button) convertView
  86. .findViewById(R.id.btn_left_audio);
  87. holderLeftAudio.tvLeftAudioTime = (TextView) convertView
  88. .findViewById(R.id.tv_left_audio_time);
  89. holderLeftAudio.tvLeftAudioTime.setText(msg.getValue());
  90. convertView.setTag(holderLeftAudio);
  91. break;
  92. // 右边
  93. case VALUE_RIGHT_TEXT:
  94. holderRightText= new ViewHolderRightText();
  95. convertView = mInflater.inflate(R.layout.list_item_right_text,
  96. null);
  97. holderRightText.ivRightIcon = (ImageView) convertView
  98. .findViewById(R.id.iv_icon);
  99. holderRightText.btnRightText = (Button) convertView
  100. .findViewById(R.id.btn_right_text);
  101. holderRightText.btnRightText.setText(msg.getValue());
  102. convertView.setTag(holderRightText);
  103. break;
  104. case VALUE_RIGHT_IMAGE:
  105. holderRightImg= new ViewHolderRightImg();
  106. convertView = mInflater.inflate(R.layout.list_item_right_iamge,
  107. null);
  108. holderRightImg.ivRightIcon = (ImageView) convertView
  109. .findViewById(R.id.iv_icon);
  110. holderRightImg.ivRightImage = (ImageView) convertView
  111. .findViewById(R.id.iv_right_image);
  112. holderRightImg.ivRightImage.setImageResource(R.drawable.test);
  113. convertView.setTag(holderRightImg);
  114. break;
  115. case VALUE_RIGHT_AUDIO:
  116. holderRightAudio=new ViewHolderRightAudio();
  117. convertView = mInflater.inflate(R.layout.list_item_right_audio,
  118. null);
  119. holderRightAudio.ivRightIcon = (ImageView) convertView
  120. .findViewById(R.id.iv_icon);
  121. holderRightAudio.btnRightAudio = (Button) convertView
  122. .findViewById(R.id.btn_right_audio);
  123. holderRightAudio.tvRightAudioTime = (TextView) convertView
  124. .findViewById(R.id.tv_right_audio_time);
  125. holderRightAudio.tvRightAudioTime.setText(msg.getValue());
  126. convertView.setTag(holderRightAudio);
  127. break;
  128. default:
  129. break;
  130. }
  131. } else {
  132. Log.d("baseAdapter", "Adapter_:"+(convertView == null) );
  133. switch (type) {
  134. case VALUE_TIME_TIP:
  135. holderTime=(ViewHolderTime)convertView.getTag();
  136. holderTime.tvTimeTip.setText(msg.getValue());
  137. break;
  138. case VALUE_LEFT_TEXT:
  139. holderLeftText=(ViewHolderLeftText)convertView.getTag();
  140. holderLeftText.btnLeftText.setText(msg.getValue());
  141. break;
  142. case VALUE_LEFT_IMAGE:
  143. holderLeftImg=(ViewHolderLeftImg)convertView.getTag();
  144. holderLeftImg.ivLeftImage.setImageResource(R.drawable.test);
  145. break;
  146. case VALUE_LEFT_AUDIO:
  147. holderLeftAudio=(ViewHolderLeftAudio)convertView.getTag();
  148. holderLeftAudio.tvLeftAudioTime.setText(msg.getValue());
  149. break;
  150. case VALUE_RIGHT_TEXT:
  151. holderRightText=(ViewHolderRightText)convertView.getTag();
  152. holderRightText.btnRightText.setText(msg.getValue());
  153. break;
  154. case VALUE_RIGHT_IMAGE:
  155. holderRightImg=(ViewHolderRightImg)convertView.getTag();
  156. holderRightImg.ivRightImage.setImageResource(R.drawable.test);
  157. break;
  158. case VALUE_RIGHT_AUDIO:
  159. holderRightAudio=(ViewHolderRightAudio)convertView.getTag();
  160. holderRightAudio.tvRightAudioTime.setText(msg.getValue());
  161. break;
  162. default:
  163. break;
  164. }
  165. //holder = (ViewHolder) convertView.getTag();
  166. }
  167. return convertView;
  168. }
  169. /**
  170. * 根据数据源的position返回需要显示的的layout的type
  171. *
  172. * type的值必须从0开始
  173. *
  174. * */
  175. @Override
  176. public int getItemViewType(int position) {
  177. Message msg = myList.get(position);
  178. int type = msg.getType();
  179. Log.e("TYPE:", "" + type);
  180. return type;
  181. }
  182. /**
  183. * 返回所有的layout的数量
  184. *
  185. * */
  186. @Override
  187. public int getViewTypeCount() {
  188. return 7;
  189. }
  190. class ViewHolderTime {
  191. private TextView tvTimeTip;// 时间
  192. }
  193. class ViewHolderRightText {
  194. private ImageView ivRightIcon;// 右边的头像
  195. private Button btnRightText;// 右边的文本
  196. }
  197. class ViewHolderRightImg {
  198. private ImageView ivRightIcon;// 右边的头像
  199. private ImageView ivRightImage;// 右边的图像
  200. }
  201. class ViewHolderRightAudio {
  202. private ImageView ivRightIcon;// 右边的头像
  203. private Button btnRightAudio;// 右边的声音
  204. private TextView tvRightAudioTime;// 右边的声音时间
  205. }
  206. class ViewHolderLeftText {
  207. private ImageView ivLeftIcon;// 左边的头像
  208. private Button btnLeftText;// 左边的文本
  209. }
  210. class ViewHolderLeftImg {
  211. private ImageView ivLeftIcon;// 左边的头像
  212. private ImageView ivLeftImage;// 左边的图像
  213. }
  214. class ViewHolderLeftAudio {
  215. private ImageView ivLeftIcon;// 左边的头像
  216. private Button btnLeftAudio;// 左边的声音
  217. private TextView tvLeftAudioTime;// 左边的声音时间
  218. }
  219. }

分享两张微信、易信的图,你也可以做成这样子。

     

注意:

使用Listview显示多样视图时,用到了getItemViewType和getViewTypeCount,但是我一运行程序就会报数组越界异常,经过查资料发现,getItemViewType的值一定要从0开始,我开始设置的type类型是从1开始的,结果就悲催了,app一直崩溃,报Java.lang.ArrayIndexOutOfBoundsException。最后把type类型改成从0开始就好了,最后注意一点,getViewTypeCount返回值一定要大于等于getItemViewType的个数。

ListView实现多种item布局的方法和注意事项的更多相关文章

  1. ListView具有多种item布局——实现微信对话列

    这篇文章的效果也是大家常见的,各种通讯应用的对话列表都是这种方式,像微信.whatsapp.易信.米聊等.我们这篇文章也权当为回忆,形成简单的笔记.这篇文章参考了2009年Google IO中的< ...

  2. 对RecycleView的多种item布局的封装

    本文是借鉴bingoogolapple写得BGAAdapter-Android而产生的,对此表示感谢. 效果 1.Adapter的使用 1.继承BaseAdapter 这里是我的adapter pub ...

  3. listView 多个item布局

    package kds.szkingdom.wo.android.adapter; import java.util.List; import android.content.Context; imp ...

  4. ListView之多种类型Item

    一.概述 一般而言,listview每个item的样式是一样的,但也有很多应用场景下不同位置的item需要不同的样式. 拿微信举例,前者的代表作是消息列表,而后者的典型则是聊天会话界面. 本文重点介绍 ...

  5. Android ListView实现不同item的方法和原理分析

    ListView实现不同item的方法和原理分析 一问题抛出Listview是android里面的重要组件,用来显示一个竖向列表,这个没有什么问题:但是有个时候列表里面的item不是一样的,如下图,列 ...

  6. RecyclerView的使用之多种Item加载布局

    精益求精,为了更加透彻熟练得掌握,本文再次给大家介石介绍下如何利用RecyclerView实现多Item布局的加载,多Item布局的加载的意思就是在开发过程中List的每一项可能根据需求的不同会加载不 ...

  7. ListView 完全优化 + 多种listitem布局处理

    #  百度了下,感觉下面的博客文章还都挺全面的,写的很好,直接分享得了 Android性能优化--Listview优化 - tonycheng93 - 博客园http://www.cnblogs.co ...

  8. Android进阶笔记11:ListView篇之ListView显示多种类型的条目(item)

    ListView可以显示多种类型的条目布局,这里写显示两种布局的情况,其他类似. 1. 这是MainActivity,MainActivity的布局就是一个ListView,太简单了这里就不写了,直接 ...

  9. 【转】Android ListView加载不同的item布局

    原创教程,转载请保留出处:http://www.eoeandroid.com/thread-72369-1-1.html     最近有需求需要在listView中载入不同的listItem布局,开始 ...

随机推荐

  1. 6 ways to import data into SQL Server

    I’m going to go over some methods to import data from text files into SQL Server today. The particul ...

  2. adb server is out of date ADB server didn't ACK * failed to start daemon *一种解决方式

           记录个小问题,这两天用到了android中的远程调试一个开发板,经常碰到一个问题,android中ADB server didn't ACK * failed to start daem ...

  3. linq join 左连接 leftjoin 多个on条件 where 条件

    var haveChange = from newScore in newScoreList join oldScore in oldScoreList on new{newScore.ExamId, ...

  4. Java SE 8 并发增强

    1.原子值 java5开始,提供了一些原子操作的类,如AtomicInteger.AtomicLong等 这些类提供了诸如incrementAndGet这样的原子操作方法. 单数如果想进行复杂操作,则 ...

  5. Redhat 5.6(RHEL 5.6)下安装PostgreSQL9.3

    1,下载Respository的更新包 http://yum.postgresql.org/9.3/redhat/rhel-5-x86_64/pgdg-redhat93-9.3-1.noarch.rp ...

  6. linux cfs调度器_模型实现

    调度器真实模型的主要成员变量及与抽象模型的对应关系 I.cfs_rq结构体    a) struct sched_entity *curr        指向当前正在执行的可调度实体.调度器的调度单位 ...

  7. How to make an HTTP request in Swift

    from: http://stackoverflow.com/questions/24016142/how-to-make-an-http-request-in-swift You can use N ...

  8. js与ios桥接使用WebViewJavascriptBridge简单理解

    https://github.com/marcuswestin/WebViewJavascriptBridge function setupWebViewJavascriptBridge(callba ...

  9. MySQL修改密码和忘记ROOT密码

    1.关闭数据库 脚本:[root@mysql etc]# service mysql stop 2.使用脚本: mysqld_safe --skip-grant-tables 启动数据库 使用/usr ...

  10. linux避免crontab的执行输出将磁盘目录占满?用户的mail占用大的空间?

    需求描述: 早上设置了ntp客户端的定时任务,发现不断的有You have new mail in /var/spool/mail/root这种提示. 然后,就看了具体的文件,由于ntpdate是每分 ...