In the session interface, the operation is primarily for session logging. As on the QQ above, the leftmost tab. Manages the session history and dynamically displays the number of messages.
Because the entire session interface is made up of fragment, there is no manifest file. Let's take a look at the composition of the layout file first.
<?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/comm ON_BG "android:orientation=" vertical "> <relativelayout android:layout_width=" match_parent "Android oid:layout_height= "@dimen/height_top_bar" android:background= "@color/top_bar_normal_bg" android:gravity= "cen Ter_vertical "> <textview android:id=" @+id/message_title "android:layout_width=" Wrap_co Ntent "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:cachecol Orhint= "#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 "and Roid:paddingbottom= "7DP" android:background= "#ededed" android:paddingleft= "@dimen/padding_search_bar" Android:pad dingright= "@dimen/padding_search_bar" > <edittext android:paddingtop= "5DP" android:paddingbottom= "5DP "Android:paddingleft=" 5DP "android:id=" @+id/query "android:layout_width=" Match_parent "Androi d:layout_height= "Wrap_content" android:layout_centervertical= "true" android:background= "@drawable/SEABAR_INP UT "android:drawableleft=" @drawable/search_bar_icon_normal "android:focusable=" true "android:focusabl Eintouchmode= "true" android:textcolorhint= "#b3b3b3" android:textsize= "16SP" Android:layout_marginleft = "4DP" Android:layout_marginright= "4DP" android:singleline= "true"/> <imagebutton android:id= "@+id/search_clear" Androi D:layout_width= "Wrap_content" android:layout_height= "Wrap_content" android:layout_alignparentright= "true" Android:layout_centervertical= "true" android:layout_marginright= "3DP" android:background= "@android: Colo R/transparent "android:padding=" 6DP "android:src=" @drawable/search_clear "android:visibility=" Invisib Le "/></relativelayout>
Can be simple, the top is a title, followed by a custom search bar, there is an error prompt bar, but the default is not displayed, the bottom is the most important component of the interface------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); //Add Session List conversationlist.addall (Loadconversationswithrecentchat ()); listview = (listView) GetView (). Findviewbyid (r.id.list); adapter = new Chatallhistoryadapter (Getactivity (), 1, conversationlist); // Set 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) { &nbs P Emconversation conversation = Adapter.getitem (position); string username = conversation.getusername (); if (Username.equals (demoapplication.getinstance () GetusernAme ())) Toast.maketext (Getactivity (), ST2, 0). Show (); else { //go to chat page & nbsp; 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 { & nbsp; //It's single chat intent.putextra ("UserId", username); } startactivity (Intent); } } }); //Registration context Menu registerforcontextmenu (listView); &nbsP;listview.setontouchlistener (New Ontouchlistener () { @ override public boolean onTouch (View V, motionevent event) {& nbsp; //Hide soft keyboard hidesoftkeyboard (); return false; } }); //search box query = ( EditText) GetView (). Findviewbyid (r.id.query); string strsearch = getresources () . getString (R.string.search); query.sethint (strsearch); //in the search box 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 { & Nbsp;clearsearch.setvisibility (view.invisible); } } public void beforetextchanged (charsequence s, int start, int count, int after) { &nbs p; } public void Aftertextchanged (Editable s) { } }); clearsearch.setonclicklistener (New Onclicklistener () { @Override public void OnClick (View v) { Query.gettext (). Clear (); Hidesoftkeyboard (); } }); }
Hide soft keyboard 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);}}
In the Onactivitycreated method, the most interface of the logical processing and data initialization process, first from the method provided by the SDK to get the session, then displayed, and set the corresponding item click event. and the corresponding processing of the query and the soft keyboard.
A context menu is also set for the session list, which allows you to delete a selected session.
@Overridepublic 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);/}} @Overridepublic 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) {deletemess Age = False;handled = true;} Emconversation tobedeletecons = Adapter.getitem (((Adaptercontextmenuinfo) Item.getmenuinfo ()). position);// Delete this session emchatmanager.getinstance (). Deleteconversation (Tobedeletecons.getusername (), Tobedeletecons.isgroup (), deleteMessage); Invitemessgedao Invitemessgedao = new Invitemessgedao (getactivity ()); Invitemessgedao.deletemessage ( Tobedeletecons.getusername ()); Adapter.remove (tobedeletecons); adapter.notifydatasetchanged ();//update message not read ((mainactivity) getactivity ()). Updateunreadlabel (); return handled? true:super.onContextItemSelected (item);}
when you delete a session, the Updateunreadlabel in main is called to update the number of unread messages.
/** * Get ALL Sessions * * @param context * @return + */private list<emconversation> loadconversationswithrecentchat () {//Get All sessions, including strangers hashtable<string, emconversation> conversations = Emchatmanager.getinstance (). GetAllConversations ( );//filter out messages size 0 conversation/** * If a new message is received during the sort process, lastmsgtime will change to affect the sorting process, Collection.sort will produce an exception * Ensure that the conversation time of the last message in the sort process is constant to avoid concurrency problems */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, have Bugsortconversationbylastchattime (sortlist);} catch (Exception e) {E.printstac Ktrace ();} list<emconversation> list = new arraylist<emconversation> (); for (Pair<long, emconversation> Sortitem:sorTList) {list.add (sortitem.second);} return list;}
/** * Sorted According to the time of the last message * * @param usernames */private void Sortconversationbylastchattime (List<pair<long, Emconversation>> conversationlist) {collections.sort (conversationlist, New Comparator<pair<long, Emconversation>> () {@Overridepublic 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;}});}
Get all session information and arrange in chronological order.
When the other tab in the main interface is clicked, it hides the current fragment, calls this method, and refreshes the interface @overridepublic void Onhiddenchanged (Boolean hidden) { Super.onhiddenchanged (hidden); This.hidden = Hidden;if (!hidden) {refresh ();}} When re-displayed and not hidden, refresh. @Overridepublic void Onresume () {super.onresume (); if (!hidden &&!) ( (mainactivity) getactivity ()). IsConflict) {refresh ();}} /** * Refresh the page and retrieve the session list when refreshed. */public void Refresh () {conversationlist.clear (); Conversationlist.addall (Loadconversationswithrecentchat ()); if ( adapter = null) adapter.notifydatasetchanged ();}
after the interface changes, the previous data is deleted and displayed again.
@Overridepublic 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);}}
Save your account information. At this point, the session list is complete, which is relatively simple.
Ring-Letter UI Open Source Demo scenario Analysis Vii. Conversational Interface