环信官方Demo源码分析及SDK简单应用-主界面的三个fragment-会话界面

环信官方Demo源码分析及SDK简单应用

环信官方Demo源码分析及SDK简单应用-ChatDemoUI3.0

环信官方Demo源码分析及SDK简单应用-LoginActivity

环信官方Demo源码分析及SDK简单应用-主界面的三个fragment-会话界面

环信官方Demo源码分析及SDK简单应用-主界面的三个fragment-通讯录界面

环信官方Demo源码分析及SDK简单应用-主界面的三个fragment-设置界面

环信官方Demo源码分析及SDK简单应用-EaseUI

环信官方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;}

上下文菜单选择的处理方法

删除消息并更新未读消息。

好,至此,第一个界面,会话界面到此结束。

我们再来看通讯录界面。

环信官方Demo源码分析及SDK简单应用-主界面的三个fragment-通讯录界面

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容