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

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

     

Demo下载,请猛击。

/**
* @author 张兴业
*  iOS入门群:83702688
*  android开发进阶群:241395671
*  我的新浪微博:@张兴业TBOW
*/

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. ListView 完全优化 + 多种listitem布局处理

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

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

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

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

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

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

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

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

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

随机推荐

  1. Django基础——Model篇(二)

    一 Model连表关系 一对多:models.ForeignKey(其他表)    多对多:models.ManyToManyField(其他表)    一对一:models.OneToOneFiel ...

  2. 负margin在布局中的运用

    一.左右栏宽度固定,中间栏宽度自适应 <!DOCTYPE html> <html> <head lang="en"> <meta char ...

  3. ios app 实现热更新(无需发新版本实现app添加新功能)

    目前能够实现热更新的方法,总结起来有以下三种 1. 使用FaceBook 的开源框架 reactive native,使用js写原生的iOS应用 ios app可以在运行时从服务器拉取最新的js文件到 ...

  4. ASP.NET Web API模型验证以及异常处理方式

    ASP.NET Web API的模型验证与ASP.NET MVC一样,都使用System.ComponentModel.DataAnnotations. 具体来说,比如有:[Required(Erro ...

  5. 一个purge参数引发的惨案——从线上hbase数据被删事故说起

    在写这篇blog前,我的心情久久不能平静,虽然明白运维工作如履薄冰,但没有料到这么一个细小的疏漏会带来如此严重的灾难.这是一起其他公司误用puppet参数引发的事故,而且这个参数我也曾被“坑过”.   ...

  6. Oracle ORA-01033: ORACLE initialization or shutdown in progress 错误解决办法

    Oracle ORA-01033: ORACLE initialization or shutdown in progress 错误解决办法 登陆数据库时提示 “ORA-01033”错误在命令窗口以s ...

  7. 安装redis监控

    在修改登录中心的时候,数据存储在redis里面,需要对redis进行监控,使用的是Redis-Live 参考文章: http://www.nkrode.com/article/real-time-da ...

  8. Python中import的使用

    python中的import语句是用来导入模块的,在python模块库中有着大量的模块可供使用,要想使用这些文件需要用import语句把指定模块导入到当前程序中. import语句的作用 import ...

  9. Gradle中ProGuard的配置

    好久没有写博客了…元旦前赶紧写一篇吧… 这些日子琢磨了一下gradle.对比起maven确实在配置上灵活很多,对groovy的支持可以更容易的自定义任务. 由于最近的几个项目中都使用到了moco这个开 ...

  10. C#版Windows服务安装卸载小工具-附源码

    前言 在我们的工作中,经常遇到Windows服务的安装和卸载,在之前公司也普写过一个WinForm程序选择安装路径,这次再来个小巧灵活的控制台程序,不用再选择,只需放到需要安装服务的目录中运行就可以实 ...