转载自:http://blog.csdn.net/xyz_lmn/article/details/13745489
这篇文章的效果也是大家常见的,各种通讯应用的对话列表都是这种方式,像微信、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
3)根据view item的类型,在getView中创建正确的convertView,重用时,也会根据当前需要的类型返回对应类型的convertView
/** * 比原来的多了getItemViewType和getViewTypeCount这两个方法, * * */ public class ChatAdapter extends BaseAdapter { public static final String KEY = "key"; public static final String VALUE = "value"; public static final int VALUE_TIME_TIP = 0;// 7种不同的布局 public static final int VALUE_LEFT_TEXT = 1; public static final int VALUE_LEFT_IMAGE = 2; public static final int VALUE_LEFT_AUDIO = 3; public static final int VALUE_RIGHT_TEXT = 4; public static final int VALUE_RIGHT_IMAGE = 5; public static final int VALUE_RIGHT_AUDIO = 6; private LayoutInflater mInflater; private List<Message> myList; public ChatAdapter(Context context, List<Message> myList) { this.myList = myList; mInflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); } @Override public int getCount() { return myList.size(); } @Override public Object getItem(int arg0) { return myList.get(arg0); } @Override public long getItemId(int arg0) { return arg0; } @Override public View getView(int position, View convertView, ViewGroup arg2) { Message msg = myList.get(position); int type = getItemViewType(position); ViewHolderTime holderTime = null; ViewHolderRightText holderRightText = null; ViewHolderRightImg holderRightImg = null; ViewHolderRightAudio holderRightAudio = null; ViewHolderLeftText holderLeftText = null; ViewHolderLeftImg holderLeftImg = null; ViewHolderLeftAudio holderLeftAudio = null; if (convertView == null) { switch (type) { case VALUE_TIME_TIP: holderTime = new ViewHolderTime(); convertView = mInflater.inflate(R.layout.list_item_time_tip, null); holderTime.tvTimeTip = (TextView) convertView .findViewById(R.id.tv_time_tip); holderTime.tvTimeTip.setText(msg.getValue()); convertView.setTag(holderTime); break; // 左边 case VALUE_LEFT_TEXT: holderLeftText = new ViewHolderLeftText(); convertView = mInflater.inflate(R.layout.list_item_left_text, null); holderLeftText.ivLeftIcon = (ImageView) convertView .findViewById(R.id.iv_icon); holderLeftText.btnLeftText = (Button) convertView .findViewById(R.id.btn_left_text); holderLeftText.btnLeftText.setText(msg.getValue()); convertView.setTag(holderLeftText); break; case VALUE_LEFT_IMAGE: holderLeftImg = new ViewHolderLeftImg(); convertView = mInflater.inflate(R.layout.list_item_left_iamge, null); holderLeftImg.ivLeftIcon = (ImageView) convertView .findViewById(R.id.iv_icon); holderLeftImg.ivLeftImage = (ImageView) convertView .findViewById(R.id.iv_left_image); holderLeftImg.ivLeftImage.setImageResource(R.drawable.test); convertView.setTag(holderLeftImg); break; case VALUE_LEFT_AUDIO: holderLeftAudio = new ViewHolderLeftAudio(); convertView = mInflater.inflate(R.layout.list_item_left_audio, null); holderLeftAudio.ivLeftIcon = (ImageView) convertView .findViewById(R.id.iv_icon); holderLeftAudio.btnLeftAudio = (Button) convertView .findViewById(R.id.btn_left_audio); holderLeftAudio.tvLeftAudioTime = (TextView) convertView .findViewById(R.id.tv_left_audio_time); holderLeftAudio.tvLeftAudioTime.setText(msg.getValue()); convertView.setTag(holderLeftAudio); break; // 右边 case VALUE_RIGHT_TEXT: holderRightText= new ViewHolderRightText(); convertView = mInflater.inflate(R.layout.list_item_right_text, null); holderRightText.ivRightIcon = (ImageView) convertView .findViewById(R.id.iv_icon); holderRightText.btnRightText = (Button) convertView .findViewById(R.id.btn_right_text); holderRightText.btnRightText.setText(msg.getValue()); convertView.setTag(holderRightText); break; case VALUE_RIGHT_IMAGE: holderRightImg= new ViewHolderRightImg(); convertView = mInflater.inflate(R.layout.list_item_right_iamge, null); holderRightImg.ivRightIcon = (ImageView) convertView .findViewById(R.id.iv_icon); holderRightImg.ivRightImage = (ImageView) convertView .findViewById(R.id.iv_right_image); holderRightImg.ivRightImage.setImageResource(R.drawable.test); convertView.setTag(holderRightImg); break; case VALUE_RIGHT_AUDIO: holderRightAudio=new ViewHolderRightAudio(); convertView = mInflater.inflate(R.layout.list_item_right_audio, null); holderRightAudio.ivRightIcon = (ImageView) convertView .findViewById(R.id.iv_icon); holderRightAudio.btnRightAudio = (Button) convertView .findViewById(R.id.btn_right_audio); holderRightAudio.tvRightAudioTime = (TextView) convertView .findViewById(R.id.tv_right_audio_time); holderRightAudio.tvRightAudioTime.setText(msg.getValue()); convertView.setTag(holderRightAudio); break; default: break; } } else { Log.d("baseAdapter", "Adapter_:"+(convertView == null) ); switch (type) { case VALUE_TIME_TIP: holderTime=(ViewHolderTime)convertView.getTag(); holderTime.tvTimeTip.setText(msg.getValue()); break; case VALUE_LEFT_TEXT: holderLeftText=(ViewHolderLeftText)convertView.getTag(); holderLeftText.btnLeftText.setText(msg.getValue()); break; case VALUE_LEFT_IMAGE: holderLeftImg=(ViewHolderLeftImg)convertView.getTag(); holderLeftImg.ivLeftImage.setImageResource(R.drawable.test); break; case VALUE_LEFT_AUDIO: holderLeftAudio=(ViewHolderLeftAudio)convertView.getTag(); holderLeftAudio.tvLeftAudioTime.setText(msg.getValue()); break; case VALUE_RIGHT_TEXT: holderRightText=(ViewHolderRightText)convertView.getTag(); holderRightText.btnRightText.setText(msg.getValue()); break; case VALUE_RIGHT_IMAGE: holderRightImg=(ViewHolderRightImg)convertView.getTag(); holderRightImg.ivRightImage.setImageResource(R.drawable.test); break; case VALUE_RIGHT_AUDIO: holderRightAudio=(ViewHolderRightAudio)convertView.getTag(); holderRightAudio.tvRightAudioTime.setText(msg.getValue()); break; default: break; } //holder = (ViewHolder) convertView.getTag(); } return convertView; } /** * 根据数据源的position返回需要显示的的layout的type * * type的值必须从0开始 * * */ @Override public int getItemViewType(int position) { Message msg = myList.get(position); int type = msg.getType(); Log.e("TYPE:", "" + type); return type; } /** * 返回所有的layout的数量 * * */ @Override public int getViewTypeCount() { return 7; } class ViewHolderTime { private TextView tvTimeTip;// 时间 } class ViewHolderRightText { private ImageView ivRightIcon;// 右边的头像 private Button btnRightText;// 右边的文本 } class ViewHolderRightImg { private ImageView ivRightIcon;// 右边的头像 private ImageView ivRightImage;// 右边的图像 } class ViewHolderRightAudio { private ImageView ivRightIcon;// 右边的头像 private Button btnRightAudio;// 右边的声音 private TextView tvRightAudioTime;// 右边的声音时间 } class ViewHolderLeftText { private ImageView ivLeftIcon;// 左边的头像 private Button btnLeftText;// 左边的文本 } class ViewHolderLeftImg { private ImageView ivLeftIcon;// 左边的头像 private ImageView ivLeftImage;// 左边的图像 } class ViewHolderLeftAudio { private ImageView ivLeftIcon;// 左边的头像 private Button btnLeftAudio;// 左边的声音 private TextView tvLeftAudioTime;// 左边的声音时间 } }
分享两张微信、易信的图,你也可以做成这样子。
源码见附件
相关推荐
在微信对话列的实现中,我们需要考虑多种类型的item布局,比如文字消息、图片消息、语音消息等,这需要用到ListView的Adapter的自定义功能。 首先,我们需要创建一个继承自BaseAdapter的自定义适配器,这个适配器将...
在Android开发中,我们经常需要实现类似微信联系人列表的功能,即按照姓名的首字母进行排序并分组显示。这个功能的核心在于理解ListView组件、数据排序以及如何利用Adapter来实现字母索引。以下是对这个话题的详细...
【标题】"安卓Android源码——高仿微信.zip"揭示了这个压缩包包含的是一个针对Android平台的开源项目,目标是实现对微信应用界面的高度模仿。这个项目旨在帮助开发者理解和学习如何在Android平台上构建类似微信的...
写的demo只有第一条item布局不一样,剩下的item布局都一样;主要用于实现在listview加上headview时又有下拉...所有就把原本listview要加的headview布局加到listview的item布局中;这样在加下拉刷新控件就不会起冲突了;
这篇文档将深入解析《安卓Android源码——简易微信客户端和服务器源码》的相关知识点,旨在帮助读者理解Android应用开发的基本原理以及如何构建一个简单的微信类通信应用。首先,我们要了解Android系统的基础架构和...
总的来说,实现Android中ListView多种Item布局的关键在于自定义BaseAdapter,并在`getView()`方法中根据数据动态决定使用哪种布局。聊天界面的实现则需要考虑消息的发送与接收,根据数据的不同属性调整布局样式。这...
这篇博客"2011.08.26——— android ListView之多个item布局"深入探讨了如何在ListView中实现多个不同类型的Item布局,这对于创建动态、丰富的用户界面至关重要。在Android应用设计中,ListView通常用于显示如联系人...
本教程将详细介绍如何在Android项目中实现“仿微信对话列表滑动删除效果”。 首先,我们需要理解滑动删除的核心原理。这种效果通常是通过在ListView或者RecyclerView等滚动视图上添加手势检测来实现的。当用户滑动...
然而,有时我们不仅仅满足于单一的列表项布局,而是希望在同一个ListView中展示多种不同的布局,这就是所谓的"ListView Item多布局"。这种功能可以使得应用界面更加丰富多彩,提供更好的用户体验。本文将详细介绍...
它允许用户滚动查看不同条目,并且可以通过自定义适配器实现多种类型的Item布局,以满足各种复杂的界面需求。本篇将深入探讨如何在Android中实现一个模拟聊天界面的ListView,其中包含两种不同的Item布局:一种用于...
博客《带checkbox的ListView实现(三)——CheckableImageView的实现方法》源码,博客地址:http://blog.csdn.net/harvic880925/article/details/41948211
在Android开发中,微信对话列表滑动删除功能是一项常见的用户交互设计,它为用户提供了一种高效、直观的方式来管理他们的聊天记录。实现这个功能主要涉及到ListView或者RecyclerView组件的自定义适配器以及手势检测...
当我们需要在一个ListView中展示多种不同类型的item布局时,这就涉及到"ListView加载多item布局"的技术。本教程将深入探讨如何实现这一功能,并结合性能优化策略,使ListView在处理大量数据时仍能保持流畅的用户体验...
- ListView是一个可滚动的视图,通常用于显示一组具有相同布局的列表项。它可以动态加载数据,以优化内存使用,提高性能。 2. **Adapter原理**: - ListView的工作离不开Adapter,它负责将数据源(如ArrayList)...
然而,当ListView需要显示多种不同的Item布局时,优化工作变得尤为重要。本教程将深入探讨如何对多种Item布局的ListView进行优化,以提高用户体验和应用性能。 1. **使用ViewHolder模式** ViewHolder模式是优化...
在提供的"ListViewSlidingMenu"文件中,可能包含了实现这一功能的示例代码,包括自定义的ListView项布局、滑动监听器、Adapter等。通过阅读和理解这些代码,开发者可以更好地掌握如何在实际项目中实现类似的功能。 ...
程序总体使用TabHost实现微信界面的四个模块,在每一个tab选项布局里使用自定义的ListView,添加ImageView和TextView控件,显示通讯录列表信息。自定义ListView的列表项布局文件,将每个ListView要显示的内容构成一个...
listview多种item
本文将深入探讨如何在Android中实现一个基于ArrayAdapter的网格布局ListView。 首先,我们要了解ListView的基本结构。ListView是由多个列表项(List Item)组成的,每个列表项通常对应一个View。在Android中,我们...
博客《Animation动画详解(十三)——实现ListView Item进入动画》对应源码,博客地址:http://blog.csdn.net/harvic880925/article/details/50988685