zoukankan      html  css  js  c++  java
  • Lance老师UI系列教程第六课>微信聊天气泡界面的实现

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

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

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

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

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

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

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

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

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

    先看看adapter的实现过程:

    public class ChatMsgViewAdapter extends BaseAdapter {
    	
    	public static interface IMsgViewType
    	{
    		int IMVT_COM_MSG = 0;
    		int IMVT_TO_MSG = 1;
    	}
    	
        private static final String TAG = ChatMsgViewAdapter.class.getSimpleName();
    
        private List<ChatMsgEntity> coll;
    
        private Context ctx;
        
        private LayoutInflater mInflater;
    
        public ChatMsgViewAdapter(Context context, List<ChatMsgEntity> coll) {
            ctx = context;
            this.coll = coll;
            mInflater = LayoutInflater.from(context);
        }
    
        public int getCount() {
            return coll.size();
        }
    
        public Object getItem(int position) {
            return coll.get(position);
        }
    
        public long getItemId(int position) {
            return position;
        }
        
    
    
    	public int getItemViewType(int position) {
    		// TODO Auto-generated method stub
    	 	ChatMsgEntity entity = coll.get(position);
    	 	
    	 	if (entity.getMsgType())
    	 	{
    	 		return IMsgViewType.IMVT_COM_MSG;
    	 	}else{
    	 		return IMsgViewType.IMVT_TO_MSG;
    	 	}
    	 	
    	}
    
    
    	public int getViewTypeCount() {
    		// TODO Auto-generated method stub
    		return 2;
    	}
    	
    	
        public View getView(int position, View convertView, ViewGroup parent) {
        	
        	ChatMsgEntity entity = coll.get(position);
        	boolean isComMsg = entity.getMsgType();
        		
        	ViewHolder viewHolder = null;	
    	    if (convertView == null)
    	    {
    	    	  if (isComMsg)
    			  {
    				  convertView = mInflater.inflate(R.layout.chatting_item_msg_text_left, null);
    			  }else{
    				  convertView = mInflater.inflate(R.layout.chatting_item_msg_text_right, null);
    			  }
    
    	    	  viewHolder = new ViewHolder();
    			  viewHolder.tvSendTime = (TextView) convertView.findViewById(R.id.tv_sendtime);
    			  viewHolder.tvUserName = (TextView) convertView.findViewById(R.id.tv_username);
    			  viewHolder.tvContent = (TextView) convertView.findViewById(R.id.tv_chatcontent);
    			  viewHolder.isComMsg = isComMsg;
    			  
    			  convertView.setTag(viewHolder);
    	    }else{
    	        viewHolder = (ViewHolder) convertView.getTag();
    	    }
    	
    	    
    	    
    	    viewHolder.tvSendTime.setText(entity.getDate());
    	    viewHolder.tvUserName.setText(entity.getName());
    	    viewHolder.tvContent.setText(entity.getText());
    	    
    	    return convertView;
        }
        
    
        static class ViewHolder { 
            public TextView tvSendTime;
            public TextView tvUserName;
            public TextView tvContent;
            public boolean isComMsg = true;
        }
    
    
    }

     

     

    看消息体的数据字段:

    public class ChatMsgEntity {
        private static final String TAG = ChatMsgEntity.class.getSimpleName();
    
        private String name;
    
        private String date;
    
        private String text;
    
        private boolean isComMeg = true;

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

     

     

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

     public View getView(int position, View convertView, ViewGroup parent) {
        	
        	ChatMsgEntity entity = coll.get(position);
        	boolean isComMsg = entity.getMsgType();
        		
        	ViewHolder viewHolder = null;	
    	    if (convertView == null)
    	    {
    	    	  if (isComMsg)
    			  {
    				  convertView = mInflater.inflate(R.layout.chatting_item_msg_text_left, null);
    			  }else{
    				  convertView = mInflater.inflate(R.layout.chatting_item_msg_text_right, null);
    			  }
    
    	    	  viewHolder = new ViewHolder();
    			  viewHolder.tvSendTime = (TextView) convertView.findViewById(R.id.tv_sendtime);
    			  viewHolder.tvUserName = (TextView) convertView.findViewById(R.id.tv_username);
    			  viewHolder.tvContent = (TextView) convertView.findViewById(R.id.tv_chatcontent);
    			  viewHolder.isComMsg = isComMsg;
    			  
    			  convertView.setTag(viewHolder);
    	    }else{
    	        viewHolder = (ViewHolder) convertView.getTag();
    	    }
    	
    	    
    	    
    	    viewHolder.tvSendTime.setText(entity.getDate());
    	    viewHolder.tvUserName.setText(entity.getName());
    	    viewHolder.tvContent.setText(entity.getText());
    	    
    	    return convertView;
        }

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

    乾坤在这里:

    public int getItemViewType(int position) {
    		// TODO Auto-generated method stub
    	 	ChatMsgEntity entity = coll.get(position);
    	 	
    	 	if (entity.getMsgType())
    	 	{
    	 		return IMsgViewType.IMVT_COM_MSG;
    	 	}else{
    	 		return IMsgViewType.IMVT_TO_MSG;
    	 	}
    	 	
    	}
    
    
    	public int getViewTypeCount() {
    		// TODO Auto-generated method stub
    		return 2;
    	}

     

    getItemViewType用来识别视图类型

    getViewTypeCount标识视图类型数量

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

     

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

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    	    android:layout_width="fill_parent"
    	    android:layout_height="wrap_content"
    	    android:orientation="vertical"
    	    android:padding="6dp">
    	
    	    <LinearLayout
    	        android:layout_width="fill_parent"
    	        android:layout_height="wrap_content"
    	        android:orientation="vertical" 
    	        android:gravity="center_horizontal">
    	
    	        <TextView
    	            android:id="@+id/tv_sendtime"
    	            android:layout_width="wrap_content"
    	            android:layout_height="wrap_content"
    	           	style="@style/chat_text_date_style"/>
    	        
    	    </LinearLayout>
    	
            
    	    <RelativeLayout
    	        android:layout_width="fill_parent"
    	        android:layout_height="wrap_content"
    	        android:layout_marginTop="5dp" >
    	        
    	         	<ImageView 
    		           android:id="@+id/iv_userhead" 
    		           android:layout_width="wrap_content"
    		           android:layout_height="wrap_content"
    		           android:focusable="false" 
    		           android:layout_alignParentLeft="true" 
                       android:layout_alignParentTop="true" 
    		           android:background="@drawable/mini_avatar_shadow"/>
     				
     				<TextView 
    	            android:id="@+id/tv_chatcontent" 
    	            android:layout_toRightOf="@id/iv_userhead"
    	            android:layout_marginLeft="10dp"
    	            android:layout_width="wrap_content"
    	            android:layout_height="wrap_content"
    	            android:background="@drawable/chatfrom_bg" 
    	          	style="@style/chat_content_date_style"/>   
    	                 
    	                  
    	            <TextView 
    	            android:id="@+id/tv_username" 
    	            android:layout_width="wrap_content"
    	            android:layout_height="wrap_content"
    	            android:layout_below="@id/iv_userhead"
    	            android:layout_alignParentLeft="true"
    	            android:layout_toLeftOf="@id/tv_chatcontent"
    	            style="@style/chat_text_name_style"/>
    	         
    	           
    	           
    	    </RelativeLayout>
    	    
    </LinearLayout>


     

    附上链接工程:

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

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

     welcome to join android develop group:298044305

     

    上一课:Lance老师UI系列教程第五课->自定义风格单选多选对话框的实现

    下一课:Lance老师UI系列教程第七课->自定义spinner下拉框实现的实现

  • 相关阅读:
    rs
    stm32f767 usoc3
    stm32f767 RTT 日志
    stm32f767 标准库 工程模板
    stm32f767 HAL 工程模板
    docker tab 补全 linux tab 补全
    docker anconda 依赖 下载 不了
    docker run 常用 指令
    linux scp 命令
    Dockerfile 常用参数说明
  • 原文地址:https://www.cnblogs.com/lance2016/p/5204227.html
Copyright © 2011-2022 走看看