Lance老师UI系列教程第六课->微信聊天气泡界面的实现

转载地址:http://blog.csdn.net/lancees/article/details/7925173


UI系列教程第六课:微信聊天气泡界面的实现

今天蓝老师要给童鞋们讲的是微信聊天界面气泡的实现

如效果图所示,许多应用即时通讯的应用软件都会涉及到聊天界面

而这样的界面使用气泡的方式来呈现要比死板的方块文字更具视觉效果

而聊天内容的背景则是用点九图来处理以便自适应文本长度

(对点九图还不熟悉的童鞋请看这篇博文:http://blog.csdn.net/geniuseoe2012/article/details/7899738

其实整体下来还是用listview+自定义baseadapter来实现

只不过传统apapter布局都是单一ITEM布局

这里则至少需要两种布局来呈现整个信息交互过程

先看看adapter的实现过程:

[java]  view plain copy
  1. public class ChatMsgViewAdapter extends BaseAdapter {  
  2.       
  3.     public static interface IMsgViewType  
  4.     {  
  5.         int IMVT_COM_MSG = 0;  
  6.         int IMVT_TO_MSG = 1;  
  7.     }  
  8.       
  9.     private static final String TAG = ChatMsgViewAdapter.class.getSimpleName();  
  10.   
  11.     private List<ChatMsgEntity> coll;  
  12.   
  13.     private Context ctx;  
  14.       
  15.     private LayoutInflater mInflater;  
  16.   
  17.     public ChatMsgViewAdapter(Context context, List<ChatMsgEntity> coll) {  
  18.         ctx = context;  
  19.         this.coll = coll;  
  20.         mInflater = LayoutInflater.from(context);  
  21.     }  
  22.   
  23.     public int getCount() {  
  24.         return coll.size();  
  25.     }  
  26.   
  27.     public Object getItem(int position) {  
  28.         return coll.get(position);  
  29.     }  
  30.   
  31.     public long getItemId(int position) {  
  32.         return position;  
  33.     }  
  34.       
  35.   
  36.   
  37.     public int getItemViewType(int position) {  
  38.         // TODO Auto-generated method stub  
  39.         ChatMsgEntity entity = coll.get(position);  
  40.           
  41.         if (entity.getMsgType())  
  42.         {  
  43.             return IMsgViewType.IMVT_COM_MSG;  
  44.         }else{  
  45.             return IMsgViewType.IMVT_TO_MSG;  
  46.         }  
  47.           
  48.     }  
  49.   
  50.   
  51.     public int getViewTypeCount() {  
  52.         // TODO Auto-generated method stub  
  53.         return 2;  
  54.     }  
  55.       
  56.       
  57.     public View getView(int position, View convertView, ViewGroup parent) {  
  58.           
  59.         ChatMsgEntity entity = coll.get(position);  
  60.         boolean isComMsg = entity.getMsgType();  
  61.               
  62.         ViewHolder viewHolder = null;     
  63.         if (convertView == null)  
  64.         {  
  65.               if (isComMsg)  
  66.               {  
  67.                   convertView = mInflater.inflate(R.layout.chatting_item_msg_text_left, null);  
  68.               }else{  
  69.                   convertView = mInflater.inflate(R.layout.chatting_item_msg_text_right, null);  
  70.               }  
  71.   
  72.               viewHolder = new ViewHolder();  
  73.               viewHolder.tvSendTime = (TextView) convertView.findViewById(R.id.tv_sendtime);  
  74.               viewHolder.tvUserName = (TextView) convertView.findViewById(R.id.tv_username);  
  75.               viewHolder.tvContent = (TextView) convertView.findViewById(R.id.tv_chatcontent);  
  76.               viewHolder.isComMsg = isComMsg;  
  77.                 
  78.               convertView.setTag(viewHolder);  
  79.         }else{  
  80.             viewHolder = (ViewHolder) convertView.getTag();  
  81.         }  
  82.       
  83.           
  84.           
  85.         viewHolder.tvSendTime.setText(entity.getDate());  
  86.         viewHolder.tvUserName.setText(entity.getName());  
  87.         viewHolder.tvContent.setText(entity.getText());  
  88.           
  89.         return convertView;  
  90.     }  
  91.       
  92.   
  93.     static class ViewHolder {   
  94.         public TextView tvSendTime;  
  95.         public TextView tvUserName;  
  96.         public TextView tvContent;  
  97.         public boolean isComMsg = true;  
  98.     }  
  99.   
  100.   
  101. }  

 

 

看消息体的数据字段:

[java]  view plain copy
  1. public class ChatMsgEntity {  
  2.     private static final String TAG = ChatMsgEntity.class.getSimpleName();  
  3.   
  4.     private String name;  
  5.   
  6.     private String date;  
  7.   
  8.     private String text;  
  9.   
  10.     private boolean isComMeg = true;  

用isComMeg来识别是外部消息还是自个儿发出去的

 

 

在getView里面根据不同类型加载不同布局:

[java]  view plain copy
  1. public View getView(int position, View convertView, ViewGroup parent) {  
  2.       
  3.     ChatMsgEntity entity = coll.get(position);  
  4.     boolean isComMsg = entity.getMsgType();  
  5.           
  6.     ViewHolder viewHolder = null;     
  7.     if (convertView == null)  
  8.     {  
  9.           if (isComMsg)  
  10.           {  
  11.               convertView = mInflater.inflate(R.layout.chatting_item_msg_text_left, null);  
  12.           }else{  
  13.               convertView = mInflater.inflate(R.layout.chatting_item_msg_text_right, null);  
  14.           }  
  15.   
  16.           viewHolder = new ViewHolder();  
  17.           viewHolder.tvSendTime = (TextView) convertView.findViewById(R.id.tv_sendtime);  
  18.           viewHolder.tvUserName = (TextView) convertView.findViewById(R.id.tv_username);  
  19.           viewHolder.tvContent = (TextView) convertView.findViewById(R.id.tv_chatcontent);  
  20.           viewHolder.isComMsg = isComMsg;  
  21.             
  22.           convertView.setTag(viewHolder);  
  23.     }else{  
  24.         viewHolder = (ViewHolder) convertView.getTag();  
  25.     }  
  26.   
  27.       
  28.       
  29.     viewHolder.tvSendTime.setText(entity.getDate());  
  30.     viewHolder.tvUserName.setText(entity.getName());  
  31.     viewHolder.tvContent.setText(entity.getText());  
  32.       
  33.     return convertView;  
  34.    }  

众所周知,listview要充分运用到缓存试图convertView,否则一旦数据量大了很容易造成OOM异常,而我们的adaper里有用到两种视图布局,又该如何去重复利用呢?

乾坤在这里:

[java]  view plain copy
  1. public int getItemViewType(int position) {  
  2.         // TODO Auto-generated method stub  
  3.         ChatMsgEntity entity = coll.get(position);  
  4.           
  5.         if (entity.getMsgType())  
  6.         {  
  7.             return IMsgViewType.IMVT_COM_MSG;  
  8.         }else{  
  9.             return IMsgViewType.IMVT_TO_MSG;  
  10.         }  
  11.           
  12.     }  
  13.   
  14.   
  15.     public int getViewTypeCount() {  
  16.         // TODO Auto-generated method stub  
  17.         return 2;  
  18.     }  

 

getItemViewType用来识别视图类型

getViewTypeCount标识视图类型数量

这样每次缓存下来的视图就总是能传递正确的对象去重复利用了

 

最后再贴一个item的布局出来:

[java]  view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.         android:layout_width="fill_parent"  
  4.         android:layout_height="wrap_content"  
  5.         android:orientation="vertical"  
  6.         android:padding="6dp">  
  7.       
  8.         <LinearLayout  
  9.             android:layout_width="fill_parent"  
  10.             android:layout_height="wrap_content"  
  11.             android:orientation="vertical"   
  12.             android:gravity="center_horizontal">  
  13.       
  14.             <TextView  
  15.                 android:id="@+id/tv_sendtime"  
  16.                 android:layout_width="wrap_content"  
  17.                 android:layout_height="wrap_content"  
  18.                 style="@style/chat_text_date_style"/>  
  19.               
  20.         </LinearLayout>  
  21.       
  22.           
  23.         <RelativeLayout  
  24.             android:layout_width="fill_parent"  
  25.             android:layout_height="wrap_content"  
  26.             android:layout_marginTop="5dp" >  
  27.               
  28.                 <ImageView   
  29.                    android:id="@+id/iv_userhead"   
  30.                    android:layout_width="wrap_content"  
  31.                    android:layout_height="wrap_content"  
  32.                    android:focusable="false"   
  33.                    android:layout_alignParentLeft="true"   
  34.                    android:layout_alignParentTop="true"   
  35.                    android:background="@drawable/mini_avatar_shadow"/>  
  36.                   
  37.                 <TextView   
  38.                 android:id="@+id/tv_chatcontent"   
  39.                 android:layout_toRightOf="@id/iv_userhead"  
  40.                 android:layout_marginLeft="10dp"  
  41.                 android:layout_width="wrap_content"  
  42.                 android:layout_height="wrap_content"  
  43.                 android:background="@drawable/chatfrom_bg"   
  44.                 style="@style/chat_content_date_style"/>     
  45.                        
  46.                         
  47.                 <TextView   
  48.                 android:id="@+id/tv_username"   
  49.                 android:layout_width="wrap_content"  
  50.                 android:layout_height="wrap_content"  
  51.                 android:layout_below="@id/iv_userhead"  
  52.                 android:layout_alignParentLeft="true"  
  53.                 android:layout_toLeftOf="@id/tv_chatcontent"  
  54.                 style="@style/chat_text_name_style"/>  
  55.                
  56.                  
  57.                  
  58.         </RelativeLayout>  
  59.           
  60. </LinearLayout>  


 

附上链接工程:

http://download.csdn.net/detail/geniuseoe2012/4536804

欲知更多Android-UI技巧,请关注窝的下一堂课,更多精彩尽在http://blog.csdn.net/geniuseoe2012

 welcome to join android develop group:298044305


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值