openfire+smack仿微信会话界面制作

在openfire服务器下制作的仿微信会话界面,包括接收用户的消息,初始化数据列表ListView,好友名称,好友头像,聊天消息,消息发送时间等,以及统计好友消息数目。

界面效果:

       openfire+smack仿微信会话界面制作_第1张图片

由于会话界面用到的是Fragment,于是想要实现自定义ListView利用到了ListFragment组件,直接让当前Fragment继承ListFragment类;然后就是Fragment的布局文件和item布局文件,将item整理成理想的样式;在Fragment中获取用户收到的好友消息,好友名,头像等,使用SimpleAdapter适配器进行数据适配;统计好友发送的消息数目,显示在UI上,已经点击item项触发事件,跳转聊天页面。

1、Fragment的布局文件fragment_one.xml,这里就仅仅是一个ListView,要注意的是ListView的id必须是Android:list,此为ListFragment指定的ListView项。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <ListView 
        android:id="@+id/android:list"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content">
    </ListView>
</LinearLayout>

2、Fragment的item项布局文件fragment_one_item.xml,将所有的内容都放在一个相对布局中,头像和时间都单独放,将好友名和好友消息放置在一个垂直布局中,最后在加上红点文本,放置在最上端显示。

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:paddingBottom="5dp"
    android:background="@drawable/linearlayout_boder">
	<LinearLayout 
	    android:layout_width="fill_parent"
	    android:layout_height="wrap_content"
	    android:layout_margin="5dp"
	    android:orientation="horizontal" >
	    <ImageView 
		    android:id="@+id/tab1_item_img"
		    android:layout_width="50dp"
		    android:layout_height="50dp"
		    android:layout_gravity="center_vertical"
	    />
	    <LinearLayout 
	        android:layout_width="0dp"
			android:layout_height="match_parent"
			android:layout_weight="0.95"
			android:layout_marginLeft="5dp"
			android:orientation="vertical"
			android:layout_gravity="center_vertical"
			android:gravity="center_vertical">
	        <TextView 
	            android:id="@+id/tab1_item_name"
	            android:layout_width="match_parent"
	            android:layout_height="wrap_content"
	            android:layout_gravity="top"
	            android:textSize="18sp"
	            android:textStyle="bold" 
	            />
	        <TextView 
	            android:id="@+id/tab1_item_text"
	            android:layout_width="match_parent"
	            android:layout_height="wrap_content"
	            android:layout_gravity="bottom"
	            android:textSize="12sp"
	            android:text="12313131313"
	           />
	    </LinearLayout>
	    <LinearLayout 
	        android:layout_width="wrap_content"
	        android:layout_height="wrap_content"
	        android:layout_gravity="top"
	        android:gravity="center_vertical"
	        android:orientation="vertical"
	        android:layout_marginTop="5dp"
	        android:layout_marginRight="5dp"
	        >
	        <TextView 
	            android:id="@+id/time"
	            android:layout_width="wrap_content"
	            android:layout_height="wrap_content"
	            android:gravity="top"
	        />
	    </LinearLayout>
	</LinearLayout>
	
	<TextView 
		android:id="@+id/number"
		android:layout_width="20dp"
		android:layout_height="20dp"
		android:layout_marginLeft="45dp"
		android:gravity="center"
		android:textColor="#FFF"
		android:background="@drawable/number"                
	/>
</RelativeLayout>
3、主界面TabFragment.java,包含获取所有好友发送的消息,使用SimpleAdapter进行ListView的数据适配,以及指定好友消息数目的统计,这里利用到两个list<Map<String,Object>>对象,其中list对象用于存储所有接收到的消息,统计指定好友消息数目;showlist显示在页面上的数据,将同一个好友发送的消息去重,仅显示最后收到的消息,并倒序显示在页面上。

package com.example.eric_jqm_chat;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Stack;

import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.ChatManager;
import org.jivesoftware.smack.ChatManagerListener;
import org.jivesoftware.smack.MessageListener;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Message;

import com.example.eric_jqm_chat.ChatActivity.ChatHandler;
import com.example.eric_jqm_chat.TabFragment4.UserAndPassword;

import android.R.color;
import android.R.string;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.ListFragment;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Adapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.SimpleAdapter.ViewBinder;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ArrayAdapter;

public class TabFragment extends ListFragment{
	
	private XMPPConnection con = ConnectServer.getInstance().getConnection();
	private UserAndPasswordOne mUserAndPassword;
	private String name,password,friend,time;
	private List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();
	private List<Map<String,Object>> showlist = new ArrayList<Map<String,Object>>();
	private SimpleAdapter adapter;
	private FragmentOneHandler handler;
	private String[] from = new String[] {"time","friend","chat","img","number"};
	private int[] to = new int[] {R.id.time,R.id.tab1_item_name,R.id.tab1_item_text,R.id.tab1_item_img,R.id.number};
	
	@Override
	public View onCreateView(LayoutInflater inflater,
			@Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
		View v = inflater.inflate(R.layout.fragment_one, container, false);
		return v;
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		name = mUserAndPassword.getUserOne(name);
		password = mUserAndPassword.getPasswordOne(password);
		
        
        //监听用户接收到的消息的副线程
        Thread thread = new Thread(new Runnable(){

  			@Override
  			public void run() {
  				//接收用户发来的消息
  				try {
					con.getChatManager().addChatListener(new ChatManagerListener() {
						
						@Override
						public void chatCreated(Chat chat, boolean arg1) {
							chat.addMessageListener(new MessageListener() {
								@Override
								public void processMessage(Chat chat, Message msg) {
									friend = msg.getFrom();
									friend = friend.substring(0, friend.indexOf("@"));
									 
									android.os.Message m = new android.os.Message();
									
									if(msg.getBody()!= null){
										Bundle b= new Bundle();
										b.putString("msg", msg.getBody());
										b.putString("friend", friend);
										m.setData(b);
										handler.sendMessage(m);
									}
								}
							});
						}
					});
					while (true);
				} catch (Exception e) {
					System.out.println("try error");
					e.printStackTrace();
				}
  				
  				
  				
  			}
  			
  		});
  		
  		thread.start();
  		
		handler = new FragmentOneHandler();
		adapter = new SimpleAdapter(getActivity(), getSimpleData(), R.layout.fragment_one_item, from, to);
		adapter.notifyDataSetChanged();//刷新listview
  		setListAdapter(adapter);
  		
  		
  		//使SimpleAdapter加载Drawable类
  		adapter.setViewBinder(new ViewBinder() {  
  		    @Override  
  		    public boolean setViewValue(View view, Object data, String arg2) {  
  		        if(view instanceof ImageView && data instanceof Drawable){  
  		            ImageView iv = (ImageView)view;  
  		            iv.setImageDrawable((Drawable)data);  
  		            return true;  
  		        }else{  
  		            return false;  
  		        }  
  		    }      
  		});   
	}
	
	
	private List<Map<String,Object>> getSimpleData(){
		
		return showlist;
	}
	
	 //将数据添加到List的函数实现  
    public void addMessageToListview(String time,String friend,String chat){  
        HashMap<String,Object> map = new HashMap<String,Object>();
        //遍历showlist去除同名的项
        try {
			for(Map<String,Object> m : showlist){
				if(m.get("friend").toString().equals(friend)){
					showlist.remove(m);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
        //添加数据到list和showlist其中list为所有收到的消息,showlist页面显示用
        map.put("time", time);
        map.put("friend", friend);
        map.put("chat", chat);
        map.put("img", new TabFragment2().getUserImage(con, friend));
        if(countNumber().get(friend)==null){
        	map.put("number", 1);
        }else{
        	map.put("number", countNumber().get(friend));
        }
        list.add(map);
        System.out.println("^^^^resultMap="+countNumber());
        showlist.add(map);
        adapter.notifyDataSetChanged();
    } 
    
	//统计好友消息数目,返回Map为好友名:消息数目
    public Map<String,Integer> countNumber(){
    	Map<String,Integer> resultMap =new HashMap<String, Integer>();
    	for(Map<String,Object> map: list){
    		for(String s: map.keySet()){
    			if(s.equals("friend")){
    				String friendName =  map.get("friend").toString();
        			Integer count = resultMap.get(friendName);
        			if(count!=null){
    					resultMap.put(friendName, count+1);
    				}else{
    					resultMap.put(friendName, 2);
        			}
    			}
    		}
    	}
		return resultMap;
    }
    
    //列表点击事件
	@Override
	public void onListItemClick(ListView l, View v, int position, long id) {
		
		//获取ListView点击位置item项的键名为friend的值,即好友名
		Map<String,Object> m = getSimpleData().get(position);
		Iterator it = m.keySet().iterator();
		Object o = m.get("friend");
		String friend = o.toString();
		
		//进行页面跳转,并传值给聊天页面ChatActivity,包括用户名密码,好友名
		Intent intent = new Intent();
		intent.setClass(getActivity(),ChatActivity.class);
		intent.putExtra("friend", friend);
		intent.putExtra("name", name);
		intent.putExtra("password", password);
		startActivity(intent);
		super.onListItemClick(l, v, position, id);
	}

	public interface UserAndPasswordOne {
		public String getUserOne(String user);
		public String getPasswordOne(String password);
	}
	
	@Override
	public void onAttach(Activity activity) {
		super.onAttach(activity);
		try {
			mUserAndPassword = (UserAndPasswordOne) activity;
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("接口实例化异常");
		}
		
	}
	
	
	public class FragmentOneHandler extends Handler{  
        @Override  
        public void handleMessage(android.os.Message msg) {  
            super.handleMessage(msg);  
            //获取接收的好友名及聊天消息  
            Bundle b = msg.getData();  
            String chatMsg = b.getString("msg");  
            String friend = b.getString("friend"); 
            
            //获取当前时间
    		SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss");       
            Date curDate = new Date(System.currentTimeMillis());     
            time = formatter.format(curDate);
            
            //添加数据到list和showlist
            addMessageToListview(time, friend, chatMsg);
            
            //将showlist按时间排成倒序
            Collections.sort(showlist, new Comparator<Map<String,Object>>() {  
                public int compare(Map<String,Object> a, Map<String,Object> b) {  
                    String at = a.get("time").toString();  
                    String bt = b.get("time").toString();  
                    if (at.compareTo(bt)<0) {  
                        return 1;  
                    } else if (at.equals(bt)) {  
                        return 0;  
                    } else {  
                        return -1;  
                    }  
                }  
            }); 
            
        }  
    }  
	
}







你可能感兴趣的:(ListView,map,openfire,smack)