这篇文章的效果也是大家常见的,各种通讯应用的对话列表都是这种方式,像微信、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

[java] view plain copy    
  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. RecyclerView实现多种item布局

    RecyclerView实现多种item布局 1.首先我们重写了getItemViewType这个方法,在这个方法中根据position对item对象做了一些判断, 2.具体为每种viewType引入 ...

  3. Flutter 15: 图解 ListView 不同样式 item 及 Widget 显隐性

    一年一度的谷歌大会又开始了,谷歌对 Flutter 的投入力度又加大了,所以更得好好学 Flutter 了.小菜在做新闻列表方面的 Demo 时,想到会在列表中展示多种不同 item 样式,今天特意借 ...

  4. ListView之多种类型Item

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

  5. android 修改listview item view 的方法(转)

    android 修改listview item view 的方法 具体的解答办法很简单: 代码如下 : 1.获取需要更新的view int visiblePosition = mListView.ge ...

  6. android开发 listview 头部 轮播,listview添加的头部布局超过一屏头部内容显示不全...

    headView的实际高度超过一个屏幕,但是显示的结果只有一个屏幕,超过一个屏幕高度意外的部分显示不全. 只使用了listView.getRefreshable().addHeadView(headV ...

  7. 安卓中PullToRefresh添加头布局的方法

    PullToRefreshListView第三方的自定义listview用起来很方便,但是有时候我们需要为这个listview添加头,由于PullToRefreshListView没有.addHead ...

  8. PullScrollView详解(五)——完全使用listview实现下拉回弹(方法二)

    前言:当你感到不舒服的时候就是成长的时候.入职阿里时学长跟我说的这句话,一直记得.到死时,人们往往不会因为自己做过什么而后悔,而常常会因为没做什么而后悔.趁你还有激情,加油! 相关文章: 1.< ...

  9. Python Qt GUI设计:窗口布局管理方法【强化】(基础篇—6)

    目录 1. 水平布局类(QHBoxLayout) 2.垂直布局类(QVBoxLayout) 3.网格布局类(QGridLayout) 3.1.单一的网络布局 3.2.跨越行.列的网络布局 4.表单布局 ...

最新文章

  1. ASP.NET温故而知新学习系列之ASP.NET多线程编程—异步编程(九)
  2. boost::callable_traits的is_const_member的测试程序
  3. linux下安装nvm进行node的版本的快速切换
  4. java 打开gc日志_在运行时打开GC日志记录
  5. Django之URLconf路由
  6. JS计算本周一和本周五的日期
  7. 【洛谷习题】南蛮图腾
  8. leetcode —— 207. 课程表
  9. 三角形垂点坐标js算法(三点定圆求圆心)
  10. java收集碎片_Thinking in Java 笔记碎片
  11. 锋利的jQuery--读书笔记
  12. [C++]最大连续子序列乘积
  13. access h3c交换机光口_华为交换机的配置及:access、trunk、hybird端口详解
  14. AD7124采集工作流程
  15. 计算机无纸化考试合卷答题笔记卡,中级会计职称无纸化答题技巧
  16. 从Unity导出Obj格式的地形(Terrian)
  17. 大疆御2电池数据查看教程
  18. python计算机器人运动学分析_V-rep学习笔记:机器人逆运动学数值解法(The Jacobian Transpose Method)...
  19. 打印菱形图案的两种方法
  20. 10-1枚举类的使用

热门文章

  1. Java 线程池ThreadPoolExecutor的应用与源码解析
  2. 实战系列-Spring Cloud微服务中三把利器Feign、Hystrix、Ribbon
  3. 深入详解Redis布隆过滤器
  4. 多级反向代理下,Java获取请求客户端的真实IP地址多中方法整合
  5. OSTaskStkInit_FPE_x86()--浮点仿真任务栈初始化函数(分段寻址的地址转换为线性地址)
  6. 解密Go协程的栈内存管理
  7. Spring Security:自定义登录页面
  8. Android 开发者的 RxJava 详解(一)
  9. [UVA] 704 Colour Hash
  10. 大数据开发 | MapReduce介绍