在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; } } } }