在会话界面中,主要是对会话记录的操作。就跟QQ上面的一样,最左边的一个Tab。管理会话历史,并动态显示消息数量。
因为整个会话界面是由Fragment所组成,所以没有清单文件。接下来咱们先来看看布局文件的构成。
<?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:background="@color/common_bg" android:orientation="vertical" > <RelativeLayout android:layout_width="match_parent" android:layout_height="@dimen/height_top_bar" android:background="@color/top_bar_normal_bg" android:gravity="center_vertical" > <TextView android:id="@+id/message_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="@string/session" android:textColor="#fff" android:textSize="18sp" /> </RelativeLayout> <include layout="@layout/search_bar" /> <include android:id="@+id/rl_error_item" layout="@layout/chat_neterror_item" android:visibility="gone" /> <ListView android:id="@+id/list" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/transparent" android:cacheColorHint="#00000000" android:divider="@null" /> </LinearLayout>
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingTop="7dp" android:paddingBottom="7dp" android:background="#ededed" android:paddingLeft="@dimen/padding_search_bar" android:paddingRight="@dimen/padding_search_bar" > <EditText android:paddingTop="5dp" android:paddingBottom="5dp" android:paddingLeft="5dp" android:id="@+id/query" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerVertical="true" android:background="@drawable/seabar_input" android:drawableLeft="@drawable/search_bar_icon_normal" android:focusable="true" android:focusableInTouchMode="true" android:textColorHint="#b3b3b3" android:textSize="16sp" android:layout_marginLeft="4dp" android:layout_marginRight="4dp" android:singleLine="true"/> <ImageButton android:id="@+id/search_clear" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:layout_marginRight="3dp" android:background="@android:color/transparent" android:padding="6dp" android:src="@drawable/search_clear" android:visibility="invisible" /> </RelativeLayout>
可以简单,最顶端是一个Title,接下来是一个自定义的搜索栏,还有一个错误提示栏,不过默认状况下是不显示的,最下面就是这个界面最重要的组成了------ListView。
@Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); if (savedInstanceState != null && savedInstanceState.getBoolean("isConflict", false)) return; inputMethodManager = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE); errorItem = (RelativeLayout) getView().findViewById(R.id.rl_error_item); errorText = (TextView) errorItem.findViewById(R.id.tv_connect_errormsg); // 添加会话列表 conversationList.addAll(loadConversationsWithRecentChat()); listView = (ListView) getView().findViewById(R.id.list); adapter = new ChatAllHistoryAdapter(getActivity(), 1, conversationList); // 设置adapter listView.setAdapter(adapter); final String st2 = getResources().getString(R.string.Cant_chat_with_yourself); listView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { EMConversation conversation = adapter.getItem(position); String username = conversation.getUserName(); if (username.equals(DemoApplication.getInstance().getUserName())) Toast.makeText(getActivity(), st2, 0).show(); else { // 进入聊天页面 Intent intent = new Intent(getActivity(), ChatActivity.class); if (conversation.isGroup()) { // it is group chat intent.putExtra("chatType", ChatActivity.CHATTYPE_GROUP); intent.putExtra("groupId", username); } else { // it is single chat intent.putExtra("userId", username); } startActivity(intent); } } }); // 注册上下文菜单 registerForContextMenu(listView); listView.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { // 隐藏软键盘 hideSoftKeyboard(); return false; } }); // 搜索框 query = (EditText) getView().findViewById(R.id.query); String strSearch = getResources().getString(R.string.search); query.setHint(strSearch); // 搜索框中清除button clearSearch = (ImageButton) getView().findViewById(R.id.search_clear); query.addTextChangedListener(new TextWatcher() { public void onTextChanged(CharSequence s, int start, int before, int count) { adapter.getFilter().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(); } }); }
// 隐藏软键盘 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); } }
在onActivityCreated方法中,最界面的逻辑处理以及数据的初始化过程,先从SDK提供的方法获取会话,然后显示出来,并且设置相应的项目点击事件。以及查询和软键盘的相应处理。
其中对会话列表还设置了上下文菜单,可以对选择的某条会话进行删除操作。
@Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); // if(((AdapterContextMenuInfo)menuInfo).position > 0){ m, getActivity().getMenuInflater().inflate(R.menu.delete_message, menu); // } } @Override public boolean onContextItemSelected(MenuItem item) { boolean handled = false; boolean deleteMessage = false; if (item.getItemId() == R.id.delete_message) { deleteMessage = true; handled = true; } else if (item.getItemId() == R.id.delete_conversation) { deleteMessage = false; handled = true; } EMConversation tobeDeleteCons = adapter.getItem(((AdapterContextMenuInfo) item.getMenuInfo()).position); // 删除此会话 EMChatManager.getInstance().deleteConversation(tobeDeleteCons.getUserName(), tobeDeleteCons.isGroup(), deleteMessage); InviteMessgeDao inviteMessgeDao = new InviteMessgeDao(getActivity()); inviteMessgeDao.deleteMessage(tobeDeleteCons.getUserName()); adapter.remove(tobeDeleteCons); adapter.notifyDataSetChanged(); // 更新消息未读数 ((MainActivity) getActivity()).updateUnreadLabel(); return handled ? true : super.onContextItemSelected(item); }
/** * 获取所有会话 * * @param context * @return + */ private List<EMConversation> loadConversationsWithRecentChat() { // 获取所有会话,包括陌生人 Hashtable<String, EMConversation> conversations = EMChatManager.getInstance().getAllConversations(); // 过滤掉messages size为0的conversation /** * 如果在排序过程中有新消息收到,lastMsgTime会发生变化 影响排序过程,Collection.sort会产生异常 * 保证Conversation在Sort过程中最后一条消息的时间不变 避免并发问题 */ List<Pair<Long, EMConversation>> sortList = new ArrayList<Pair<Long, EMConversation>>(); synchronized (conversations) { for (EMConversation conversation : conversations.values()) { if (conversation.getAllMessages().size() != 0) { sortList.add(new Pair<Long, EMConversation>(conversation.getLastMessage().getMsgTime(), conversation)); } } } try { // Internal is TimSort algorithm, has bug sortConversationByLastChatTime(sortList); } catch (Exception e) { e.printStackTrace(); } List<EMConversation> list = new ArrayList<EMConversation>(); for (Pair<Long, EMConversation> sortItem : sortList) { list.add(sortItem.second); } return list; }
/** * 根据最后一条消息的时间排序 * * @param usernames */ private void sortConversationByLastChatTime(List<Pair<Long, EMConversation>> conversationList) { Collections.sort(conversationList, new Comparator<Pair<Long, EMConversation>>() { @Override public int compare(final Pair<Long, EMConversation> con1, final Pair<Long, EMConversation> con2) { if (con1.first == con2.first) { return 0; } else if (con2.first > con1.first) { return 1; } else { return -1; } } }); }
获得所有会话信息,并按照时间顺序进行排列。
//当点击MAIN界面中其他Tab的时候会隐藏当前Fragment,调用此方法,并且刷新界面 @Override public void onHiddenChanged(boolean hidden) { super.onHiddenChanged(hidden); this.hidden = hidden; if (!hidden) { refresh(); } } //当重新显示,并且没有隐藏的话,刷新。 @Override public void onResume() { super.onResume(); if (!hidden && !((MainActivity) getActivity()).isConflict) { refresh(); } } /** * 刷新页面, 刷新的时候重新获取会话列表。 */ public void refresh() { conversationList.clear(); conversationList.addAll(loadConversationsWithRecentChat()); if (adapter != null) adapter.notifyDataSetChanged(); }在界面改变之后删除之前数据,重新显示。
@Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); if (((MainActivity) getActivity()).isConflict) { outState.putBoolean("isConflict", true); } else if (((MainActivity) getActivity()).getCurrentAccountRemoved()) { outState.putBoolean(Constant.ACCOUNT_REMOVED, true); } }保存账号信息。至此,会话列表就完成了,其中比较简单。
原文地址:http://blog.csdn.net/caowei0403/article/details/45305961