类似微信的聊天界面ListView

时间:2021-03-21 19:36:24

微信中的ListView有一个特点就是存在许多不同的Item,即并不是平常的ListView,所有的Item布局都是一样的。针对这种情况,Google的Adapter提供了两个方法getItemViewType和getViewTypeCount。通过覆盖这两个方法就可以实现一个ListView中存在多种不同的Layout。实现了更加个性化的ListView效果。我归纳了下微信中的Item可以分为7中。针对这7种Item我对应地写了7中listItem。在getView的时候判断下当前数据对象中需要通过哪种布局来展现,来实时获取布局。

 

下面看代码:

 

Message.java

 

Java代码  类似微信的聊天界面ListView
  1. public class Message {  
  2.   
  3.     private int type;//指定是哪种类型  
  4.     private String value;//值  
  5.     public int getType() {  
  6.         return type;  
  7.     }  
  8.     public void setType(int type) {  
  9.         this.type = type;  
  10.     }  
  11.     public String getValue() {  
  12.         return value;  
  13.     }  
  14.     public void setValue(String value) {  
  15.         this.value = value;  
  16.     }  
  17. }  

 

 

MainActivity.java:

 

Java代码  类似微信的聊天界面ListView
  1. public class MainActivity extends Activity {  
  2.   
  3.     private ListView lvData;  
  4.       
  5.     @Override  
  6.     protected void onCreate(Bundle savedInstanceState) {  
  7.         super.onCreate(savedInstanceState);  
  8.         setContentView(R.layout.activity_main);  
  9.           
  10.         lvData = (ListView)findViewById(R.id.lv_data);  
  11.           
  12.         lvData.setAdapter(getAdapter());  
  13.     }  
  14.   
  15.     private BaseAdapter getAdapter(){  
  16.           
  17.         return new MyAdapter(this, getMyData());  
  18.     }  
  19.       
  20.     private List<Message> getMyData(){  
  21.           
  22.         List<Message> msgList = new ArrayList<Message>();  
  23.         Message msg;  
  24.         msg = new Message();  
  25.         msg.setType(MyAdapter.VALUE_LEFT_TEXT);  
  26.         msg.setValue("食堂真难吃啊");  
  27.         msgList.add(msg);  
  28.           
  29.         msg = new Message();  
  30.         msg.setType(MyAdapter.VALUE_TIME_TIP);  
  31.         msg.setValue("2012-12-23 下午2:23");  
  32.         msgList.add(msg);  
  33.           
  34.         msg = new Message();  
  35.         msg.setType(MyAdapter.VALUE_RIGHT_TEXT);  
  36.         msg.setValue("我就说食堂的饭难吃吧,你不相信!");  
  37.         msgList.add(msg);  
  38.           
  39.         msg = new Message();  
  40.         msg.setType(MyAdapter.VALUE_LEFT_TEXT);  
  41.         msg.setValue("好吧,这次听你的了。");  
  42.         msgList.add(msg);  
  43.           
  44.         msg = new Message();  
  45.         msg.setType(MyAdapter.VALUE_TIME_TIP);  
  46.         msg.setValue("2012-12-23 下午2:25");  
  47.         msgList.add(msg);  
  48.           
  49.         msg = new Message();  
  50.         msg.setType(MyAdapter.VALUE_RIGHT_TEXT);  
  51.         msg.setValue("就要圣诞了,有什么安排没有?");  
  52.         msgList.add(msg);  
  53.   
  54.         msg = new Message();  
  55.         msg.setType(MyAdapter.VALUE_LEFT_TEXT);  
  56.         msg.setValue("没有啊,你呢?");  
  57.         msgList.add(msg);  
  58.           
  59.         msg = new Message();  
  60.         msg.setType(MyAdapter.VALUE_TIME_TIP);  
  61.         msg.setValue("2012-12-23 下午3:25");  
  62.         msgList.add(msg);  
  63.           
  64.         msg = new Message();  
  65.         msg.setType(MyAdapter.VALUE_LEFT_IMAGE);  
  66.         msg.setValue("7min");  
  67.         msgList.add(msg);  
  68.           
  69.         msg = new Message();  
  70.         msg.setType(MyAdapter.VALUE_RIGHT_TEXT);  
  71.         msg.setValue("高帅富有三宝 木耳 跑车 和名表," +  
  72.                 "黑木耳有三宝 美瞳 备胎 黑丝脚 ,穷矮挫有三宝 AV 手纸 射得早 ,女神有三宝 干嘛 呵呵 去洗澡 ,宅男有三宝 Dota 基友 破电脑 " +  
  73.                 "女屌丝有三宝 虎背 熊腰 眼睛小 , 女屌丝还有三宝 饼脸 花痴 卖萌照");  
  74.         msgList.add(msg);  
  75.           
  76.         msg = new Message();  
  77.         msg.setType(MyAdapter.VALUE_LEFT_TEXT);  
  78.         msg.setValue("碉堡了");  
  79.         msgList.add(msg);  
  80.           
  81.         msg = new Message();  
  82.         msg.setType(MyAdapter.VALUE_LEFT_AUDIO);  
  83.         msg.setValue("7min");  
  84.         msgList.add(msg);  
  85.           
  86.         msg = new Message();  
  87.         msg.setType(MyAdapter.VALUE_RIGHT_IMAGE);  
  88.         msg.setValue("7min");  
  89.         msgList.add(msg);  
  90.           
  91.         return msgList;  
  92.           
  93.     }  
  94.       
  95.       
  96. }  
 

下面是最重要的地方:

 

MyAdapter.java:

 

Java代码  类似微信的聊天界面ListView
  1. public class MyAdapter extends BaseAdapter{  
  2.   
  3.       
  4.     public static final String KEY = "key";  
  5.     public static final String VALUE = "value";  
  6.       
  7.     public static final int VALUE_TIME_TIP = 0;//7种不同的布局  
  8.     public static final int VALUE_LEFT_TEXT = 1;  
  9.     public static final int VALUE_LEFT_IMAGE = 2;  
  10.     public static final int VALUE_LEFT_AUDIO = 3;  
  11.     public static final int VALUE_RIGHT_TEXT = 4;  
  12.     public static final int VALUE_RIGHT_IMAGE = 5;  
  13.     public static final int VALUE_RIGHT_AUDIO = 6;  
  14.     private LayoutInflater mInflater;  
  15.       
  16.     private Context context;  
  17.     private List<Message> myList;  
  18.     public MyAdapter(Context context, List<Message> myList){  
  19.           
  20.         this.context = context;  
  21.         this.myList = myList;  
  22.           
  23.         for(Message msg:myList){  
  24.               
  25.             Log.d("myList:", msg.getType()+"");  
  26.         }  
  27.           
  28.         mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);  
  29.     }  
  30.       
  31.     public void addItem(final Message item) {  
  32.         myList.add(item);  
  33.         notifyDataSetChanged();  
  34.     }  
  35.       
  36.     @Override  
  37.     public int getCount() {  
  38.         return myList.size();  
  39.     }  
  40.   
  41.     @Override  
  42.     public Object getItem(int arg0) {  
  43.         return myList.get(arg0);  
  44.     }  
  45.   
  46.     @Override  
  47.     public long getItemId(int arg0) {  
  48.         return arg0;  
  49.     }  
  50.   
  51.     @Override  
  52.     public View getView(int position, View convertView, ViewGroup arg2) {  
  53.           
  54.         Message msg = myList.get(position);  
  55.         int type = getItemViewType(position);  
  56.         ViewHolder holder = null;  
  57.         if(convertView == null){  
  58.               
  59.             holder = new ViewHolder();  
  60.                 switch (type) {  
  61.                     case VALUE_TIME_TIP:  
  62.                           
  63.                         convertView = mInflater.inflate(R.layout.list_item_time_tip, null);  
  64.                         holder.tvTimeTip = (TextView)convertView.findViewById(R.id.tv_time_tip);  
  65.                         holder.tvTimeTip.setText(msg.getValue());  
  66.                         break;  
  67.                                 //左边  
  68.                     case VALUE_LEFT_TEXT:  
  69.                           
  70.                         convertView = mInflater.inflate(R.layout.list_item_left_text, null);  
  71.                         holder.ivLeftIcon = (ImageView)convertView.findViewById(R.id.iv_icon);  
  72.                         holder.btnLeftText = (Button)convertView.findViewById(R.id.btn_left_text);  
  73.                         holder.btnLeftText.setText(msg.getValue());  
  74.                         break;  
  75.                           
  76.                     case VALUE_LEFT_IMAGE:  
  77.                           
  78.                         convertView = mInflater.inflate(R.layout.list_item_left_iamge, null);  
  79.                         holder.ivLeftIcon = (ImageView)convertView.findViewById(R.id.iv_icon);  
  80.                         holder.ivLeftImage = (ImageView)convertView.findViewById(R.id.iv_left_image);  
  81.                         holder.ivLeftImage.setImageResource(R.drawable.test);  
  82.                         break;  
  83.                           
  84.                     case VALUE_LEFT_AUDIO:  
  85.       
  86.                         convertView = mInflater.inflate(R.layout.list_item_left_audio, null);  
  87.                         holder.ivLeftIcon = (ImageView)convertView.findViewById(R.id.iv_icon);  
  88.                         holder.btnLeftAudio = (Button)convertView.findViewById(R.id.btn_left_audio);  
  89.                         holder.tvLeftAudioTime = (TextView)convertView.findViewById(R.id.tv_left_audio_time);  
  90.                         holder.tvLeftAudioTime.setText(msg.getValue());  
  91.                         break;  
  92.                                 //右边  
  93.                     case VALUE_RIGHT_TEXT:  
  94.                           
  95.                         convertView = mInflater.inflate(R.layout.list_item_right_text, null);  
  96.                         holder.ivRightIcon = (ImageView)convertView.findViewById(R.id.iv_icon);  
  97.                         holder.btnRightText = (Button)convertView.findViewById(R.id.btn_right_text);  
  98.                         holder.btnRightText.setText(msg.getValue());  
  99.                         break;  
  100.                           
  101.                     case VALUE_RIGHT_IMAGE:  
  102.                           
  103.                         convertView = mInflater.inflate(R.layout.list_item_right_iamge, null);  
  104.                         holder.ivRightIcon = (ImageView)convertView.findViewById(R.id.iv_icon);  
  105.                         holder.ivRightImage = (ImageView)convertView.findViewById(R.id.iv_right_image);  
  106.                         holder.ivRightImage.setImageResource(R.drawable.test);  
  107.                         break;  
  108.                           
  109.                     case VALUE_RIGHT_AUDIO:  
  110.       
  111.                         convertView = mInflater.inflate(R.layout.list_item_right_audio, null);  
  112.                         holder.ivRightIcon = (ImageView)convertView.findViewById(R.id.iv_icon);  
  113.                         holder.btnRightAudio = (Button)convertView.findViewById(R.id.btn_right_audio);  
  114.                         holder.tvRightAudioTime = (TextView)convertView.findViewById(R.id.tv_right_audio_time);  
  115.                         holder.tvRightAudioTime.setText(msg.getValue());  
  116.                         break;  
  117.                           
  118.                     default:  
  119.                         break;  
  120.                 }  
  121.                 convertView.setTag(holder);  
  122.             }else{  
  123.                 holder = (ViewHolder)convertView.getTag();  
  124.             }  
  125.             return convertView;  
  126.         }  
  127.       
  128.     /** 
  129.      * 根据数据源的position返回需要显示的的layout的type 
  130.      *  
  131.      * */  
  132.     @Override  
  133.     public int getItemViewType(int position) {  
  134.           
  135.         Message msg = myList.get(position);  
  136.         int type = msg.getType();  
  137.         Log.e("TYPE:"""+type);  
  138.         return type;  
  139.     }  
  140.   
  141.     /** 
  142.      * 返回所有的layout的数量 
  143.      *  
  144.      * */  
  145.     @Override  
  146.     public int getViewTypeCount() {  
  147.         return 7;  
  148.     }  
  149.       
  150.     class ViewHolder{  
  151.           
  152.         private TextView tvTimeTip;//时间  
  153.           
  154.         private ImageView ivLeftIcon;//左边的头像  
  155.         private Button btnLeftText;//左边的文本  
  156.         private ImageView ivLeftImage;//左边的图像  
  157.         private Button btnLeftAudio;//左边的声音  
  158.         private TextView tvLeftAudioTime;//左边的声音时间  
  159.           
  160.         private ImageView ivRightIcon;//右边的头像  
  161.         private Button btnRightText;//右边的文本  
  162.         private ImageView ivRightImage;//右边的图像  
  163.         private Button btnRightAudio;//右边的声音  
  164.         private TextView tvRightAudioTime;//右边的声音时间  
  165.     }  
  166.   
  167. }  

 

在getView()的时候通过switch判断当前一条数据需要使用的是哪种布局,实时进行加载。

getItemViewType() 和getViewTypeCount() 这两个方法起到的作用是循环回收利用不同的布局,起到了优化的作用!这是不同于平时使用Adapter的地方。

 

 

效果如下:

 

类似微信的聊天界面ListView

 

 

项目地址:

 

https://github.com/michaelye/WeiXinListView