您的位置:首页 > 产品设计 > UI/UE

环信UI开源Demo情景分析七、会话界面

2015-04-27 09:15 344 查看
在会话界面中,主要是对会话记录的操作。就跟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);
}


当删除会话后调用Main中的updateUnreadLabel更新未读消息数。

/**
* 获取所有会话
*
* @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);
}
}
保存账号信息。至此,会话列表就完成了,其中比较简单。

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