环信官方Demo源码分析及SDK简单应用-ChatDemoUI3.0
环信官方Demo源码分析及SDK简单应用-LoginActivity
环信官方Demo源码分析及SDK简单应用-主界面的三个fragment-会话界面
环信官方Demo源码分析及SDK简单应用-主界面的三个fragment-通讯录界面
环信官方Demo源码分析及SDK简单应用-主界面的三个fragment-设置界面
环信官方Demo源码分析及SDK简单应用-IM集成开发详案及具体代码实现
现在来看具体的主界面的三个Fragment
主界面的三个fragment
会话界面
我们来看会话界面的代码
package com.hyphenate.chatuidemo.ui;
import android.content.Intent;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.easemob.redpacketsdk.constant.RPConstant;
import com.hyphenate.chat.EMClient;
import com.hyphenate.chat.EMConversation;
import com.hyphenate.chat.EMConversation.EMConversationType;
import com.hyphenate.chat.EMMessage;
import com.hyphenate.chatuidemo.Constant;
import com.hyphenate.chatuidemo.R;
import com.hyphenate.chatuidemo.db.InviteMessgeDao;
import com.hyphenate.easeui.model.EaseAtMessageHelper;
import com.hyphenate.easeui.ui.EaseConversationListFragment;
import com.hyphenate.easeui.widget.EaseConversationList.EaseConversationListHelper;
import com.hyphenate.util.NetUtils;
public class ConversationListFragment extends EaseConversationListFragment{
private TextView errorText;
@Override
protected void initView() {
super.initView();
View errorView = (LinearLayout) View.inflate(getActivity(),R.layout.em_chat_neterror_item, null);
errorItemContainer.addView(errorView);
errorText = (TextView) errorView.findViewById(R.id.tv_connect_errormsg);
}
@Override
protected void setUpView() {
super.setUpView();
// register context menu
registerForContextMenu(conversationListView);
conversationListView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView parent, View view, int position, long id) {
EMConversation conversation = conversationListView.getItem(position);
String username = conversation.conversationId();
if (username.equals(EMClient.getInstance().getCurrentUser()))
Toast.makeText(getActivity(), R.string.Cant_chat_with_yourself, Toast.LENGTH_SHORT).show();
else {
// start chat acitivity
Intent intent = new Intent(getActivity(), ChatActivity.class);
if(conversation.isGroup()){
if(conversation.getType() == EMConversationType.ChatRoom){
// it's group chat
intent.putExtra(Constant.EXTRA_CHAT_TYPE, Constant.CHATTYPE_CHATROOM);
}else{
intent.putExtra(Constant.EXTRA_CHAT_TYPE, Constant.CHATTYPE_GROUP);
}
}
// it's single chat
intent.putExtra(Constant.EXTRA_USER_ID, username);
startActivity(intent);
}
}
});
//red packet code : 红包回执消息在会话列表最后一条消息的展示
conversationListView.setConversationListHelper(new EaseConversationListHelper() {
@Override
public String onSetItemSecondaryText(EMMessage lastMessage) {
if (lastMessage.getBooleanAttribute(RPConstant.MESSAGE_ATTR_IS_RED_PACKET_ACK_MESSAGE, false)) {
String sendNick = lastMessage.getStringAttribute(RPConstant.EXTRA_RED_PACKET_SENDER_NAME, "");
String receiveNick = lastMessage.getStringAttribute(RPConstant.EXTRA_RED_PACKET_RECEIVER_NAME, "");
String msg;
if (lastMessage.direct() == EMMessage.Direct.RECEIVE) {
msg = String.format(getResources().getString(R.string.msg_someone_take_red_packet), receiveNick);
} else {
if (sendNick.equals(receiveNick)) {
msg = getResources().getString(R.string.msg_take_red_packet);
} else {
msg = String.format(getResources().getString(R.string.msg_take_someone_red_packet), sendNick);
}
}
return msg;
} else if (lastMessage.getBooleanAttribute(RPConstant.MESSAGE_ATTR_IS_TRANSFER_PACKET_MESSAGE, false)) {
String transferAmount = lastMessage.getStringAttribute(RPConstant.EXTRA_TRANSFER_AMOUNT, "");
String msg;
if (lastMessage.direct() == EMMessage.Direct.RECEIVE) {
msg = String.format(getResources().getString(R.string.msg_transfer_to_you), transferAmount);
} else {
msg = String.format(getResources().getString(R.string.msg_transfer_from_you),transferAmount);
}
return msg;
}
return null;
}
});
super.setUpView();
//end of red packet code
}
@Override
protected void onConnectionDisconnected() {
super.onConnectionDisconnected();
if (NetUtils.hasNetwork(getActivity())){
errorText.setText(R.string.can_not_connect_chat_server_connection);
} else {
errorText.setText(R.string.the_current_network);
}
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
getActivity().getMenuInflater().inflate(R.menu.em_delete_message, menu);
}
@Override
public boolean onContextItemSelected(MenuItem item) {
boolean deleteMessage = false;
if (item.getItemId() == R.id.delete_message) {
deleteMessage = true;
} else if (item.getItemId() == R.id.delete_conversation) {
deleteMessage = false;
}
EMConversation tobeDeleteCons = conversationListView.getItem(((AdapterContextMenuInfo) item.getMenuInfo()).position);
if (tobeDeleteCons == null) {
return true;
}
if(tobeDeleteCons.getType() == EMConversationType.GroupChat){
EaseAtMessageHelper.get().removeAtMeGroup(tobeDeleteCons.conversationId());
}
try {
// delete conversation
EMClient.getInstance().chatManager().deleteConversation(tobeDeleteCons.conversationId(), deleteMessage);
InviteMessgeDao inviteMessgeDao = new InviteMessgeDao(getActivity());
inviteMessgeDao.deleteMessage(tobeDeleteCons.conversationId());
} catch (Exception e) {
e.printStackTrace();
}
refresh();
// update unread count
((MainActivity) getActivity()).updateUnreadLabel();
return true;
}
}
我们还是挨个来读代码
public class ConversationListFragment extends EaseConversationListFragment
来,我们还是得先去找他爹算账。
public class EaseConversationListFragment extends EaseBaseFragment
哎呀,我们再去找他爷爷。
public abstract class EaseBaseFragment extends Fragment
爷爷终于正常点是从Android系统类继承下来的了,我们看具体的代码
EaseBaseFragment
package com.hyphenate.easeui.ui;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.View;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import com.hyphenate.easeui.R;
import com.hyphenate.easeui.widget.EaseTitleBar;
public abstract class EaseBaseFragment extends Fragment{
protected EaseTitleBar titleBar;
protected InputMethodManager inputMethodManager;
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
inputMethodManager = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
//noinspection ConstantConditions
titleBar = (EaseTitleBar) getView().findViewById(R.id.title_bar);
initView();
setUpView();
}
public void showTitleBar(){
if(titleBar != null){
titleBar.setVisibility(View.VISIBLE);
}
}
public void hideTitleBar(){
if(titleBar != null){
titleBar.setVisibility(View.GONE);
}
}
protected void hideSoftKeyboard() {
if (getActivity().getWindow().getAttributes().softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN) {
if (getActivity().getCurrentFocus() != null)
inputMethodManager.hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(),
InputMethodManager.HIDE_NOT_ALWAYS);
}
}
protected abstract void initView();
protected abstract void setUpView();
}
我们还是挨个来看代码,研究他的功能。
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
inputMethodManager = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
//noinspection ConstantConditions
titleBar = (EaseTitleBar) getView().findViewById(R.id.title_bar);
initView();
setUpView();
}
隐藏输入法
看到inputmethdManager要干嘛啊,隐藏键盘。果不其然。
protected void hideSoftKeyboard() {
if (getActivity().getWindow().getAttributes().softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN) {
if (getActivity().getCurrentFocus() != null)
inputMethodManager.hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(),
InputMethodManager.HIDE_NOT_ALWAYS);
}
}
然后呢?
初始化标题头
//noinspection ConstantConditions
titleBar = (EaseTitleBar) getView().findViewById(R.id.title_bar);
最后初始化标题头,并且让子孙们去实现抽象方法initView和setUpView().
隐藏和显示标题头
其中还提供了两个方法,隐藏和显示标题头
public void showTitleBar(){
if(titleBar != null){
titleBar.setVisibility(View.VISIBLE);
}
}
public void hideTitleBar(){
if(titleBar != null){
titleBar.setVisibility(View.GONE);
}
}
好了,爷爷的帐算完了,我们来找他儿子。
EaseConversationListFragment
我们来看代码
package com.hyphenate.easeui.ui;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Pair;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import com.hyphenate.EMConnectionListener;
import com.hyphenate.EMConversationListener;
import com.hyphenate.EMError;
import com.hyphenate.chat.EMClient;
import com.hyphenate.chat.EMConversation;
import com.hyphenate.easeui.R;
import com.hyphenate.easeui.widget.EaseConversationList;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
/**
* conversation list fragment
*
*/
public class EaseConversationListFragment extends EaseBaseFragment{
private final static int MSG_REFRESH = 2;
protected EditText query;
protected ImageButton clearSearch;
protected boolean hidden;
protected List conversationList = new ArrayList();
protected EaseConversationList conversationListView;
protected FrameLayout errorItemContainer;
protected boolean isConflict;
protected EMConversationListener convListener = new EMConversationListener(){
@Override
public void onCoversationUpdate() {
refresh();
}
};
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.ease_fragment_conversation_list, container, false);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
if(savedInstanceState != null && savedInstanceState.getBoolean("isConflict", false))
return;
super.onActivityCreated(savedInstanceState);
}
@Override
protected void initView() {
inputMethodManager = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
conversationListView = (EaseConversationList) getView().findViewById(R.id.list);
query = (EditText) getView().findViewById(R.id.query);
// button to clear content in search bar
clearSearch = (ImageButton) getView().findViewById(R.id.search_clear);
errorItemContainer = (FrameLayout) getView().findViewById(R.id.fl_error_item);
}
@Override
protected void setUpView() {
conversationList.addAll(loadConversationList());
conversationListView.init(conversationList);
if(listItemClickListener != null){
conversationListView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView parent, View view, int position, long id) {
EMConversation conversation = conversationListView.getItem(position);
listItemClickListener.onListItemClicked(conversation);
}
});
}
EMClient.getInstance().addConnectionListener(connectionListener);
query.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence s, int start, int before, int count) {
conversationListView.filter(s);
if (s.length() > 0) {
clearSearch.setVisibility(View.VISIBLE);
} else {
clearSearch.setVisibility(View.INVISIBLE);
}
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void afterTextChanged(Editable s) {
}
});
clearSearch.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
query.getText().clear();
hideSoftKeyboard();
}
});
conversationListView.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
hideSoftKeyboard();
return false;
}
});
}
protected EMConnectionListener connectionListener = new EMConnectionListener() {
@Override
public void onDisconnected(int error) {
if (error == EMError.USER_REMOVED || error == EMError.USER_LOGIN_ANOTHER_DEVICE || error == EMError.SERVER_SERVICE_RESTRICTED) {
isConflict = true;
} else {
handler.sendEmptyMessage(0);
}
}
@Override
public void onConnected() {
handler.sendEmptyMessage(1);
}
};
private EaseConversationListItemClickListener listItemClickListener;
protected Handler handler = new Handler(){
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case 0:
onConnectionDisconnected();
break;
case 1:
onConnectionConnected();
break;
case MSG_REFRESH:
{
conversationList.clear();
conversationList.addAll(loadConversationList());
conversationListView.refresh();
break;
}
default:
break;
}
}
};
/**
* connected to server
*/
protected void onConnectionConnected(){
errorItemContainer.setVisibility(View.GONE);
}
/**
* disconnected with server
*/
protected void onConnectionDisconnected(){
errorItemContainer.setVisibility(View.VISIBLE);
}
/**
* refresh ui
*/
public void refresh() {
if(!handler.hasMessages(MSG_REFRESH)){
handler.sendEmptyMessage(MSG_REFRESH);
}
}
/**
* load conversation list
*
* @return
+ */
protected List loadConversationList(){
// get all conversations
Map conversations = EMClient.getInstance().chatManager().getAllConversations();
List> sortList = new ArrayList>();
/**
* lastMsgTime will change if there is new message during sorting
* so use synchronized to make sure timestamp of last message won't change.
*/
synchronized (conversations) {
for (EMConversation conversation : conversations.values()) {
if (conversation.getAllMessages().size() != 0) {
sortList.add(new Pair(conversation.getLastMessage().getMsgTime(), conversation));
}
}
}
try {
// Internal is TimSort algorithm, has bug
sortConversationByLastChatTime(sortList);
} catch (Exception e) {
e.printStackTrace();
}
List list = new ArrayList();
for (Pair sortItem : sortList) {
list.add(sortItem.second);
}
return list;
}
/**
* sort conversations according time stamp of last message
*
* @param conversationList
*/
private void sortConversationByLastChatTime(List> conversationList) {
Collections.sort(conversationList, new Comparator>() {
@Override
public int compare(final Pair con1, final Pair con2) {
if (con1.first.equals(con2.first)) {
return 0;
} else if (con2.first.longValue() > con1.first.longValue()) {
return 1;
} else {
return -1;
}
}
});
}
protected void hideSoftKeyboard() {
if (getActivity().getWindow().getAttributes().softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN) {
if (getActivity().getCurrentFocus() != null)
inputMethodManager.hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(),
InputMethodManager.HIDE_NOT_ALWAYS);
}
}
@Override
public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
this.hidden = hidden;
if (!hidden && !isConflict) {
refresh();
}
}
@Override
public void onResume() {
super.onResume();
if (!hidden) {
refresh();
}
}
@Override
public void onDestroy() {
super.onDestroy();
EMClient.getInstance().removeConnectionListener(connectionListener);
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if(isConflict){
outState.putBoolean("isConflict", true);
}
}
public interface EaseConversationListItemClickListener {
/**
* click event for conversation list
* @param conversation -- clicked item
*/
void onListItemClicked(EMConversation conversation);
}
/**
* set conversation list item click listener
* @param listItemClickListener
*/
public void setConversationListItemClickListener(EaseConversationListItemClickListener listItemClickListener){
this.listItemClickListener = listItemClickListener;
}
}
填充布局
首先onCreateView(),正常的填充了布局
return inflater.inflate(R.layout.ease_fragment_conversation_list, container, false);
继续看代码
@Override
public void onActivityCreated(Bundle savedInstanceState) {
if(savedInstanceState != null && savedInstanceState.getBoolean("isConflict", false))
return;
super.onActivityCreated(savedInstanceState);
}
判断冲突标志位
@Override
protected void initView() {
inputMethodManager = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
conversationListView = (EaseConversationList) getView().findViewById(R.id.list);
query = (EditText) getView().findViewById(R.id.query);
// button to clear content in search bar
clearSearch = (ImageButton) getView().findViewById(R.id.search_clear);
errorItemContainer = (FrameLayout) getView().findViewById(R.id.fl_error_item);
}
initView()
覆写爷爷的家规,初始化View输入法管理器
会话列表List
查找联系人的输入框
清除搜索的按钮
errorItemContainer 错误标签容器
继续看代码setUpView()方法
setUpView()
conversationList.addAll(loadConversationList());
conversationListView.init(conversationList);
if(listItemClickListener != null){
conversationListView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView parent, View view, int position, long id) {
EMConversation conversation = conversationListView.getItem(position);
listItemClickListener.onListItemClicked(conversation);
}
});
}
EMClient.getInstance().addConnectionListener(connectionListener);
query.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence s, int start, int before, int count) {
conversationListView.filter(s);
if (s.length() > 0) {
clearSearch.setVisibility(View.VISIBLE);
} else {
clearSearch.setVisibility(View.INVISIBLE);
}
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void afterTextChanged(Editable s) {
}
});
clearSearch.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
query.getText().clear();
hideSoftKeyboard();
}
});
conversationListView.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
hideSoftKeyboard();
return false;
}
});
我们一句句的看
conversationList.addAll(loadConversationList());
conversationListView.init(conversationList);
会话列表添加全部以及数据填充初始化。
我们来看具体的方法
/**
* load conversation list
*
* @return
*/
protected List loadConversationList(){
// get all conversations
Map conversations = EMClient.getInstance().chatManager().getAllConversations();
List> sortList = new ArrayList>();
/**
* lastMsgTime will change if there is new message during sorting
* so use synchronized to make sure timestamp of last message won't change.
*/
synchronized (conversations) {
for (EMConversation conversation : conversations.values()) {
if (conversation.getAllMessages().size() != 0) {
sortList.add(new Pair(conversation.getLastMessage().getMsgTime(), conversation));
}
}
}
try {
// Internal is TimSort algorithm, has bug
sortConversationByLastChatTime(sortList);
} catch (Exception e) {
e.printStackTrace();
}
List list = new ArrayList();
for (Pair sortItem : sortList) {
list.add(sortItem.second);
}
return list;
}
loadConversationList()返回一个EMConversation对象List。
// get all conversations
Map conversations = EMClient.getInstance().chatManager().getAllConversations();
List> sortList = new ArrayList>();
通过封装的chatManager拿到所有的会话列表
/**
* lastMsgTime will change if there is new message during sorting
* so use synchronized to make sure timestamp of last message won't change.
*/
synchronized (conversations) {
for (EMConversation conversation : conversations.values()) {
if (conversation.getAllMessages().size() != 0) {
sortList.add(new Pair(conversation.getLastMessage().getMsgTime(), conversation));
}
}
}
lastMsgTime会随着新消息的到来排序发生改变,所以我们用同步方法确保最新消息的时间戳不发生改变。
英文不好,大致是这么个意思。
try {
// Internal is TimSort algorithm, has bug
sortConversationByLastChatTime(sortList);
} catch (Exception e) {
e.printStackTrace();
}
List list = new ArrayList();
for (Pair sortItem : sortList) {
list.add(sortItem.second);
}
return list;
其中还特地注释了一把,算法有点bug。
/**
* sort conversations according time stamp of last message
*
* @param conversationList
*/
private void sortConversationByLastChatTime(List> conversationList) {
Collections.sort(conversationList, new Comparator>() {
@Override
public int compare(final Pair con1, final Pair con2) {
if (con1.first.equals(con2.first)) {
return 0;
} else if (con2.first.longValue() > con1.first.longValue()) {
return 1;
} else {
return -1;
}
}
});
根据最新的会话时间戳来排序。
我们接着看
List list = new ArrayList();
for (Pair sortItem : sortList) {
list.add(sortItem.second);
}
return list;
添加完了返回list。
conversationListView.init(conversationList);
接着就初始化了。
if(listItemClickListener != null){
conversationListView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView parent, View view, int position, long id) {
EMConversation conversation = conversationListView.getItem(position);
listItemClickListener.onListItemClicked(conversation);
}
});
}
然后便是连接接听
EMClient.getInstance().addConnectionListener(connectionListener);
添加了一个连接的监听。
protected EMConnectionListener connectionListener = new EMConnectionListener() {
@Override
public void onDisconnected(int error) {
if (error == EMError.USER_REMOVED || error == EMError.USER_LOGIN_ANOTHER_DEVICE || error == EMError.SERVER_SERVICE_RESTRICTED) {
isConflict = true;
} else {
handler.sendEmptyMessage(0);
}
}
@Override
public void onConnected() {
handler.sendEmptyMessage(1);
}
};
在断开连接时判断用户是否移除,是否在其他设备登陆,或者服务端的服务受到限制,是的话则标记冲突。不是则发送handler空消息。
protected Handler handler = new Handler(){
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case 0:
onConnectionDisconnected();
break;
case 1:
onConnectionConnected();
break;
case MSG_REFRESH:
{
conversationList.clear();
conversationList.addAll(loadConversationList());
conversationListView.refresh();
break;
}
default:
break;
}
}
};
干嘛啊?调用 onConnectionDisconnected 即连接断开的处理方法
/**
* disconnected with server
*/
protected void onConnectionDisconnected(){
errorItemContainer.setVisibility(View.VISIBLE);
}
即显示错误条。
我们再接着看代码
query.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence s, int start, int before, int count) {
conversationListView.filter(s);
if (s.length() > 0) {
clearSearch.setVisibility(View.VISIBLE);
} else {
clearSearch.setVisibility(View.INVISIBLE);
}
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void afterTextChanged(Editable s) {
}
});
clearSearch.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
query.getText().clear();
hideSoftKeyboard();
}
});
conversationListView.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
hideSoftKeyboard();
return false;
}
});
干了些什么啊?查询、清除搜索、会话列表点击监听。
其他方法
/**
* connected to server
*/
protected void onConnectionConnected(){
errorItemContainer.setVisibility(View.GONE);
}
连接后将错误条隐藏
case MSG_REFRESH:
{
conversationList.clear();
conversationList.addAll(loadConversationList());
conversationListView.refresh();
break;
}
服务器告诉要刷新了,那么我们就去清楚列表,然后去服务器拿并排序,然后刷新listview。其中该listview为自定义的EaseConversationList。
那么儿子齐活了,我们再看孙子
ConversationListFragment
package com.hyphenate.chatuidemo.ui;
import android.content.Intent;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.easemob.redpacketsdk.constant.RPConstant;
import com.hyphenate.chat.EMClient;
import com.hyphenate.chat.EMConversation;
import com.hyphenate.chat.EMConversation.EMConversationType;
import com.hyphenate.chat.EMMessage;
import com.hyphenate.chatuidemo.Constant;
import com.hyphenate.chatuidemo.R;
import com.hyphenate.chatuidemo.db.InviteMessgeDao;
import com.hyphenate.easeui.model.EaseAtMessageHelper;
import com.hyphenate.easeui.ui.EaseConversationListFragment;
import com.hyphenate.easeui.widget.EaseConversationList.EaseConversationListHelper;
import com.hyphenate.util.NetUtils;
public class ConversationListFragment extends EaseConversationListFragment{
private TextView errorText;
@Override
protected void initView() {
super.initView();
View errorView = (LinearLayout) View.inflate(getActivity(),R.layout.em_chat_neterror_item, null);
errorItemContainer.addView(errorView);
errorText = (TextView) errorView.findViewById(R.id.tv_connect_errormsg);
}
@Override
protected void setUpView() {
super.setUpView();
// register context menu
registerForContextMenu(conversationListView);
conversationListView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView parent, View view, int position, long id) {
EMConversation conversation = conversationListView.getItem(position);
String username = conversation.conversationId();
if (username.equals(EMClient.getInstance().getCurrentUser()))
Toast.makeText(getActivity(), R.string.Cant_chat_with_yourself, Toast.LENGTH_SHORT).show();
else {
// start chat acitivity
Intent intent = new Intent(getActivity(), ChatActivity.class);
if(conversation.isGroup()){
if(conversation.getType() == EMConversationType.ChatRoom){
// it's group chat
intent.putExtra(Constant.EXTRA_CHAT_TYPE, Constant.CHATTYPE_CHATROOM);
}else{
intent.putExtra(Constant.EXTRA_CHAT_TYPE, Constant.CHATTYPE_GROUP);
}
}
// it's single chat
intent.putExtra(Constant.EXTRA_USER_ID, username);
startActivity(intent);
}
}
});
//red packet code : 红包回执消息在会话列表最后一条消息的展示
conversationListView.setConversationListHelper(new EaseConversationListHelper() {
@Override
public String onSetItemSecondaryText(EMMessage lastMessage) {
if (lastMessage.getBooleanAttribute(RPConstant.MESSAGE_ATTR_IS_RED_PACKET_ACK_MESSAGE, false)) {
String sendNick = lastMessage.getStringAttribute(RPConstant.EXTRA_RED_PACKET_SENDER_NAME, "");
String receiveNick = lastMessage.getStringAttribute(RPConstant.EXTRA_RED_PACKET_RECEIVER_NAME, "");
String msg;
if (lastMessage.direct() == EMMessage.Direct.RECEIVE) {
msg = String.format(getResources().getString(R.string.msg_someone_take_red_packet), receiveNick);
} else {
if (sendNick.equals(receiveNick)) {
msg = getResources().getString(R.string.msg_take_red_packet);
} else {
msg = String.format(getResources().getString(R.string.msg_take_someone_red_packet), sendNick);
}
}
return msg;
} else if (lastMessage.getBooleanAttribute(RPConstant.MESSAGE_ATTR_IS_TRANSFER_PACKET_MESSAGE, false)) {
String transferAmount = lastMessage.getStringAttribute(RPConstant.EXTRA_TRANSFER_AMOUNT, "");
String msg;
if (lastMessage.direct() == EMMessage.Direct.RECEIVE) {
msg = String.format(getResources().getString(R.string.msg_transfer_to_you), transferAmount);
} else {
msg = String.format(getResources().getString(R.string.msg_transfer_from_you),transferAmount);
}
return msg;
}
return null;
}
});
super.setUpView();
//end of red packet code
}
@Override
protected void onConnectionDisconnected() {
super.onConnectionDisconnected();
if (NetUtils.hasNetwork(getActivity())){
errorText.setText(R.string.can_not_connect_chat_server_connection);
} else {
errorText.setText(R.string.the_current_network);
}
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
getActivity().getMenuInflater().inflate(R.menu.em_delete_message, menu);
}
@Override
public boolean onContextItemSelected(MenuItem item) {
boolean deleteMessage = false;
if (item.getItemId() == R.id.delete_message) {
deleteMessage = true;
} else if (item.getItemId() == R.id.delete_conversation) {
deleteMessage = false;
}
EMConversation tobeDeleteCons = conversationListView.getItem(((AdapterContextMenuInfo) item.getMenuInfo()).position);
if (tobeDeleteCons == null) {
return true;
}
if(tobeDeleteCons.getType() == EMConversationType.GroupChat){
EaseAtMessageHelper.get().removeAtMeGroup(tobeDeleteCons.conversationId());
}
try {
// delete conversation
EMClient.getInstance().chatManager().deleteConversation(tobeDeleteCons.conversationId(), deleteMessage);
InviteMessgeDao inviteMessgeDao = new InviteMessgeDao(getActivity());
inviteMessgeDao.deleteMessage(tobeDeleteCons.conversationId());
} catch (Exception e) {
e.printStackTrace();
}
refresh();
// update unread count
((MainActivity) getActivity()).updateUnreadLabel();
return true;
}
}
initView()
@Override
protected void initView() {
super.initView();
View errorView = (LinearLayout) View.inflate(getActivity(),R.layout.em_chat_neterror_item, null);
errorItemContainer.addView(errorView);
errorText = (TextView) errorView.findViewById(R.id.tv_connect_errormsg);
}
添加了错误的容器、初始化错误消息控件。
registerForContextMenu(conversationListView);
注册上下文菜单
conversationListView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView parent, View view, int position, long id) {
EMConversation conversation = conversationListView.getItem(position);
String username = conversation.conversationId();
if (username.equals(EMClient.getInstance().getCurrentUser()))
Toast.makeText(getActivity(), R.string.Cant_chat_with_yourself, Toast.LENGTH_SHORT).show();
else {
// start chat acitivity
Intent intent = new Intent(getActivity(), ChatActivity.class);
if(conversation.isGroup()){
if(conversation.getType() == EMConversationType.ChatRoom){
// it's group chat
intent.putExtra(Constant.EXTRA_CHAT_TYPE, Constant.CHATTYPE_CHATROOM);
}else{
intent.putExtra(Constant.EXTRA_CHAT_TYPE, Constant.CHATTYPE_GROUP);
}
}
// it's single chat
intent.putExtra(Constant.EXTRA_USER_ID, username);
startActivity(intent);
}
}
});
条目的点击监听
其中做了这么些事情:
判断用户名是否等于当前登陆用户,是则提示不能跟自己聊天
如果是群聊的话,则继续判断是聊天室还是群组,并带值给ChatActivity即聊天界面
最后将用户名带上,跳转ChatActivity。
//red packet code : 红包回执消息在会话列表最后一条消息的展示
conversationListView.setConversationListHelper(new EaseConversationListHelper() {
@Override
public String onSetItemSecondaryText(EMMessage lastMessage) {
if (lastMessage.getBooleanAttribute(RPConstant.MESSAGE_ATTR_IS_RED_PACKET_ACK_MESSAGE, false)) {
String sendNick = lastMessage.getStringAttribute(RPConstant.EXTRA_RED_PACKET_SENDER_NAME, "");
String receiveNick = lastMessage.getStringAttribute(RPConstant.EXTRA_RED_PACKET_RECEIVER_NAME, "");
String msg;
if (lastMessage.direct() == EMMessage.Direct.RECEIVE) {
msg = String.format(getResources().getString(R.string.msg_someone_take_red_packet), receiveNick);
} else {
if (sendNick.equals(receiveNick)) {
msg = getResources().getString(R.string.msg_take_red_packet);
} else {
msg = String.format(getResources().getString(R.string.msg_take_someone_red_packet), sendNick);
}
}
return msg;
} else if (lastMessage.getBooleanAttribute(RPConstant.MESSAGE_ATTR_IS_TRANSFER_PACKET_MESSAGE, false)) {
String transferAmount = lastMessage.getStringAttribute(RPConstant.EXTRA_TRANSFER_AMOUNT, "");
String msg;
if (lastMessage.direct() == EMMessage.Direct.RECEIVE) {
msg = String.format(getResources().getString(R.string.msg_transfer_to_you), transferAmount);
} else {
msg = String.format(getResources().getString(R.string.msg_transfer_from_you),transferAmount);
}
return msg;
}
return null;
}
});
super.setUpView();
最后是红包回执信息。
我们接着看其他的方法
@Override
protected void onConnectionDisconnected() {
super.onConnectionDisconnected();
if (NetUtils.hasNetwork(getActivity())){
errorText.setText(R.string.can_not_connect_chat_server_connection);
} else {
errorText.setText(R.string.the_current_network);
}
}
端口网络则提示没网标签。
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
getActivity().getMenuInflater().inflate(R.menu.em_delete_message, menu);
}
创建上下文菜单
@Overridepublic boolean onContextItemSelected(MenuItem item) { boolean deleteMessage = false; if (item.getItemId() == R.id.delete_message) { deleteMessage = true; } else if (item.getItemId() == R.id.delete_conversation) { deleteMessage = false; } EMConversation tobeDeleteCons = conversationListView.getItem(((AdapterContextMenuInfo) item.getMenuInfo()).position); if (tobeDeleteCons == null) { return true; } if(tobeDeleteCons.getType() == EMConversationType.GroupChat){ EaseAtMessageHelper.get().removeAtMeGroup(tobeDeleteCons.conversationId()); } try { // delete conversation EMClient.getInstance().chatManager().deleteConversation(tobeDeleteCons.conversationId(), deleteMessage); InviteMessgeDao inviteMessgeDao = new InviteMessgeDao(getActivity()); inviteMessgeDao.deleteMessage(tobeDeleteCons.conversationId()); } catch (Exception e) { e.printStackTrace(); } refresh(); // update unread count[url=http://www.imgeek.org/article/825308690]环信官方Demo源码分析及SDK简单应用-主界面的三个fragment-通讯录界面[/url] ((MainActivity) getActivity()).updateUnreadLabel(); return true;}
上下文菜单选择的处理方法
删除消息并更新未读消息。
好,至此,第一个界面,会话界面到此结束。
我们再来看通讯录界面。