您的位置:首页 > 运维架构

openfire+smack使用ListFragment加载好友列表

2015-08-29 08:11 357 查看
在Activity中加载自定义ListView的时候,需要自定义适配器类继承BaseAdapter类,但Fragment中使用自定义的ListView,则使用ListFragment来实现和SimpleAdapter适配器。

效果图:


                 


一、使用ListFragment加载好友列表实现思路

1、编写ListFragment的布局文件fragment_two.xml,其中定义好ListView的位置,且ListView的id必须定义为android:list

2、编写子定义ListView的每个项布局文件fragment_two_item.xml

3、编写Fragment2.java类继承ListFragment类,使用SimpleAdapter适配器适配ListView内容,ListViewitem点击事件跳转到指定好友聊天界面。

二、功能具体实现

1、ListFragment的布局文件fragment_two.xml

<?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" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@drawable/linearlayout_boder"
>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:orientation="horizontal"
android:background="#FFF"
>
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginLeft="5dp"
android:layout_gravity="center_vertical"
android:background="@drawable/newfriend"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:layout_marginLeft="5dp"
android:textSize="18sp"
android:textStyle="bold"
android:text="新朋友"
/>
</LinearLayout>
</LinearLayout>

<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@drawable/linearlayout_boder"
>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:orientation="horizontal"
android:background="#FFF" >
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginLeft="5dp"
android:layout_gravity="center_vertical"
android:background="@drawable/grouptalk"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:layout_marginLeft="5dp"
android:textSize="18sp"
android:textStyle="bold"
android:text="群聊"
/>
</LinearLayout>
</LinearLayout>

<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@drawable/linearlayout_boder"
>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:orientation="horizontal"
android:background="#FFF">
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginLeft="5dp"
android:layout_gravity="center_vertical"
android:background="@drawable/tips"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:layout_marginLeft="5dp"
android:textSize="18sp"
android:textStyle="bold"
android:text="标签"
/>
</LinearLayout>
</LinearLayout>
<ListView
android:id="@+id/android:list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
></ListView>

</LinearLayout>
2、ListView的每个项布局文件fragment_two_item.xml

<?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:background="@drawable/linearlayout_boder">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:orientation="horizontal" >
<ImageView
android:id="@+id/tab2_item_img"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginLeft="5dp"
android:layout_gravity="center_vertical"
/>
<TextView
android:id="@+id/tab2_item_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:layout_marginLeft="5dp"
android:textSize="18sp"
android:textStyle="bold"
/>
</LinearLayout>
</LinearLayout>
3、主界面Fragment2.java
package com.example.eric_jqm_chat;

import java.io.ByteArrayInputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.provider.ProviderManager;
import org.jivesoftware.smackx.packet.VCard;

import com.example.eric_jqm_chat.TabFragment.UserAndPasswordOne;

import android.app.Activity;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.ListFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.SimpleAdapter.ViewBinder;
import android.widget.Toast;

public class TabFragment2 extends ListFragment {
//创建连接对象
private XMPPConnection con = new ConnectServer().ConnectServer();
//获得接口实例,该接口用来获取从前一个Activity传来的登录用户的用户名和密码
private UserAndPasswordTwo mUserAndPassword;
private String name ,password;
//Roster对象,可以通过Roster对象实例后进行获取好友列表
private Roster roster;

@Override
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
//加载Fragment2的布局文件
return inflater.inflate(R.layout.fragment_two, container, false);
}

@Override
public void onCreate(Bundle savedInstanceState) {
//定义键名称和指定控件id
final String[] str = new String[]{"img","name"};
final int[] id = new int[]{R.id.tab2_item_img,R.id.tab2_item_name};

super.onCreate(savedInstanceState);

//获取用户名和密码,该方法在前面的博文:Activity与Fragment相互传递参数
//有介绍,这里不再赘述
name = mUserAndPassword.getUserTwo(name);
password = mUserAndPassword.getPasswordTwo(password);
//登录用户
try {
con.login(name, password);
} catch (XMPPException e) {
e.printStackTrace();
}

//使用SimpleAdapter进行适配ListView内容
SimpleAdapter adapter = new SimpleAdapter(getActivity(), getSimpleData(),
R.layout.fragment_two_item, str, id);
this.setListAdapter(adapter);

//SimpleAdapter只能为控件适配drawable目录下的图片即R.drawable.XX
//为了适应我们从服务器获取的Drawable类型图片,必须使用到ViewBinder类
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;
}
}
});

}

//获取ListView适配的数据类
private List<Map<String,Object>> getSimpleData(){
List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();

//实例化Roster对象
roster = con.getRoster();
//通过getallEntries()获取Roster对象的好友列表
List<RosterEntry> friendList = this.getallEntries(roster);
//创建键值对
Map<String, Object> map = new HashMap<String, Object>();
//
for(int i=0;i<friendList.size();i++){
map = new HashMap<String, Object>();
map.put("name",friendList.get(i).getName());
//从服务器获取好友头像
Drawable imgDrawable = this.getUserImage(con, friendList.get(i).getName());
//若用户未设置头像则使用本地默认头像
if(imgDrawable == null){
map.put("img", R.drawable.user);
}else{
map.put("img", imgDrawable);
}
list.add(map);
}
//System.out.println("list===="+list);
return list;

}

//ListView点击事件
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
Toast.makeText(getActivity(), "Select"+position, Toast.LENGTH_SHORT).show();
//获取点击位置ListView项键名为name的值,即好友的用户名
Map<String,Object> m = getSimpleData().get(position);
Iterator it = m.keySet().iterator();
Object o = m.get("name");
String friend = o.toString();
//System.out.println("friend=="+friend);

//进行页面跳转,并传值给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);
}

//获取Activity传来的用户名密码的接口声明
public interface UserAndPasswordTwo {
public String getUserTwo(String user);
public String getPasswordTwo(String password);
}

@Override
public void onAttach(Activity activity) {

super.onAttach(activity);
try {
mUserAndPassword = (UserAndPasswordTwo) activity;
} catch (Exception e) {
e.printStackTrace();
System.out.println("接口实例化异常");
}

}

//查询所有好友信息
public List<RosterEntry> getallEntries(Roster roster) {
List<RosterEntry> Entrieslist = new ArrayList<RosterEntry>();
Collection<RosterEntry> rosterEntry = roster.getEntries();
Iterator<RosterEntry> i = rosterEntry.iterator();
while (i.hasNext()) {
Entrieslist.add(i.next());
}
return Entrieslist;
}

//获取指定用户头像类
public Drawable getUserImage(XMPPConnection con,String user) {
ByteArrayInputStream bais =null;

if (con == null)
return null;

try {
VCard vcard = new VCard();

ProviderManager.getInstance().addIQProvider("vCard", "vcard-temp",
new org.jivesoftware.smackx.provider.VCardProvider());

vcard.load(con, user.trim()+"@"+con.getServiceName());

if (user == "" || user == null || user.trim().length() <= 0) {
//Toast.makeText(Login.this, "user为空", 0).show();
return null;
}

if (vcard == null || vcard.getAvatar() == null){
//Toast.makeText(Login.this, "Vcard为空", 0).show();
return null;
}

bais = new ByteArrayInputStream(vcard.getAvatar());

} catch (Exception e) {
e.printStackTrace();
// Toast.makeText(Login.this, "图片获取异常"+e, 0).show();
// System.out.println("图片获取异常: "+e);
return null;
}
return FormatTools.getInstance().InputStream2Drawable(bais);
}
}
4、聊天界面ChatActivity.java
package com.example.eric_jqm_chat;
//聊天界面ChatActivity的详细制作在前面的博文:openfire+smack聊天气泡效果ListView完成收发消息
//有详细介绍,本章就主要描述从Fragment传过来的值怎么使用
//首先使用获得的用户名密码登录,获得自己的头像,根据好友们获得好友头像
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;

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

import android.app.Activity;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;

/*
*@author Eric
*@create date 2015-8-25下午8:51:17
*/

public class ChatActivity extends Activity {
private TextView text_chat,text_title;
private EditText edit_chat;
private ImageView img_send;
private Drawable img_userDrawable,img_friendDrawable;
private XMPPConnection con = new ConnectServer().ConnectServer();
private String str_text,name,password,friend,sendMsg;
private ChatHandler handler;
private SimpleDateFormat sf = new SimpleDateFormat("HH:mm");

private ArrayList<HashMap<String, Object>> chatList = new ArrayList<HashMap<String,Object>>();
String[] from = {"img","text"};
int[] to = {R.id.img_me,R.id.text_me,R.id.img_friend,R.id.text_friend};
int[] item_layout = {R.layout.i_sendmsg_item,R.layout.friend_sendmsg_item};
private ListView listview_chat;
private MyAdapter myAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.chat);

img_send = (ImageView) findViewById(R.id.img_send);
edit_chat = (EditText) findViewById(R.id.edit_chat);
listview_chat = (ListView) findViewById(R.id.listview_chat);
text_title = (TextView) findViewById(R.id.text_title);

myAdapter = new MyAdapter(this, chatList, item_layout, from, to);

//获取从Fragment传过来的值
name = getIntent().getStringExtra("name");
password = getIntent().getStringExtra("password");
friend = getIntent().getStringExtra("friend");
text_title.setText(friend);
try {
con.login(name, password);
} catch (XMPPException e) {
e.printStackTrace();
}

//获取用户头像和好友头像
img_userDrawable = new TabFragment2().getUserImage(con, name);
img_friendDrawable = new TabFragment2().getUserImage(con, friend);

img_send.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View arg0) {
sendMsg = edit_chat.getText().toString();

Chat chat = con.getChatManager().createChat(friend+"@"+"eric-pc", null);
try {
chat.sendMessage(sendMsg);
} catch (XMPPException e) {
e.printStackTrace();
}

edit_chat.setText(null);

addChatToListview(0, sendMsg);

//将ListView设置为置底显示,自动刷新UI,使得消息及时显示
listview_chat.setAdapter(myAdapter);
listview_chat.setSelection(myAdapter.getCount()-1);
}
});

//监听用户接收到的消息的副线程
Thread thread = new Thread(new Runnable(){

@Override
public void run() {
//接收用户发来的消息
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);
}

}
});
}
});

}

});

thread.start();
handler = new ChatHandler();

}

public class ChatHandler extends Handler{
@Override
public void handleMessage(android.os.Message msg) {
super.handleMessage(msg);

Bundle b = msg.getData();
String ChatHandler = b.getString("msg");
String friend = b.getString("friend");

text_title.setText(friend);
addChatToListview(1, ChatHandler);

//将ListView设置为置底显示,自动刷新UI,使得消息及时显示
listview_chat.setAdapter(myAdapter);
listview_chat.setSelection(myAdapter.getCount()-1);

}
}

public void addChatToListview(int who,String chat){
HashMap<String,Object> map = new HashMap<String,Object>();
map.put("who", who);
map.put("img", who==0?R.drawable.touxiang1:R.drawable.touxiang5);
map.put("chat", chat);
chatList.add(map);
}

public class MyAdapter extends BaseAdapter{
Context context;
ArrayList<HashMap<String,Object>> chatList= null;
int[] layout;
String[] from;
int[] to;
LayoutInflater listcontainer;

public MyAdapter(Context context,
ArrayList<HashMap<String, Object>> chatList, int[] layout,
String[] from, int[] to){

super();
this.context = context;
listcontainer = LayoutInflater.from(context);
this.chatList = chatList;
this.layout = layout;
this.from = from;
this.to = to;
}

@Override
public int getCount() {
return chatList.size();
}

@Override
public Object getItem(int arg0) {
return null;
}

@Override
public long getItemId(int ItemId) {
return ItemId;
}

@Override
public View getView(int item, View view, ViewGroup parent) {
//获取当前子项的who和chat
int who = (Integer)chatList.get(item).get("who");
String msg = (String)chatList.get(item).get("chat");
//根据who设置当前子项的布局和文本,0为自己发送的布局,1为好友发送的布局
if(who==0)
{
view=listcontainer.inflate(R.layout.i_sendmsg_item, null);
((TextView)view.findViewById(R.id.text_me)).setText(msg);
((ImageView)view.findViewById(R.id.img_me)).setImageDrawable(img_userDrawable);
return view;
}
else
{
view=listcontainer.inflate(R.layout.friend_sendmsg_item, null);
((TextView)view.findViewById(R.id.text_friend)).setText(msg);
((ImageView)view.findViewById(R.id.img_friend)).setImageDrawable(img_friendDrawable);
return view;
}
}

}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: