Reprinted please indicate the source: http://blog.csdn.net/guolin_blog/article/details/9033553
I remember that I was very interested in the special effects in the system contact when I first came into contact with Android. It will be grouped based on the first letter of the contact's last name on the mobile phone, the current group is always displayed at the top of the page. As shown in:
What interests me most is that when the last group is in touch with the previous group, a top-up squeeze animation will be generated. At that time, I thought about various methods to implement this special effect, but I was not able to succeed because I had no efforts. Now more than two years have passed, and I have grown a lot. Now I think about this function, and I suddenly find that I already have the idea, so I will immediately record it and share it with you.
First, let's talk about the knowledge points we need to know in advance. Here we need sectionindexer, which can effectively help us control groups. Because sectionindexer is an interface, you can customize a subclass to implement sectionindexer. However, it is too troublesome to write another sectionindexer. Here, we directly use the Android-provided alphabetindexer implementation, it is sufficient to use it to implement the Contact Group function.
The alphabetindexer constructor requires three parameters. The first parameter is cursor, the second parameter is sortedcolumnindex, and the third parameter is the alphabet string. The cursor transmits the cursor we found from the database. The sortedcolumnindex indicates which column is used for sorting, while the alphabet specifies the alphabetic sorting rules, for example: "abcdefghijklmnopqrstuvwxyz ". With alphabetindexer, we can use its getpositionforsection and getsectionforposition methods to find the group where the current position is located and the location where the current group is located, this allows you to achieve group navigation and extrusion animation effects similar to system contacts. For more details about alphabetindexer, see the official documentation.
So how should we sort contacts? As mentioned above, there is a sortedcolumnindex parameter. Where is this sortedcolumn? Let's take a look at the raw_contacts table (/data/COM. android. providers. contacts/databases/contacts2.db). This table has a complex structure and contains more than 20 columns, one of which is named sort_key. This is what we are looking! As shown in:
We can see that this column records the pinyin corresponding to Chinese characters in a very user-friendly manner, so that we can easily sort contacts by the values in this column.
Next we will start to implement it. Create an android project named contactsdemo. First, complete the layout file, open or create activity_main.xml as the main layout file of the program, and add the following code to it:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <ListView android:id="@+id/contacts_list_view" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:fadingEdge="none" > </ListView> <LinearLayout android:id="@+id/title_layout" android:layout_width="fill_parent" android:layout_height="18dip" android:layout_alignParentTop="true" android:background="#303030" > <TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginLeft="10dip" android:textColor="#ffffff" android:textSize="13sp" /> </LinearLayout></RelativeLayout>
The layout file is very simple. A listview is placed in it to display the contact information. In addition, a linearlayout header contains a textview, which is used to display a current group at all times in the interface header.
Create a new contact_item.xml layout for filling each row in the listview. The Code is as follows:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <LinearLayout android:id="@+id/sort_key_layout" android:layout_width="fill_parent" android:layout_height="18dip" android:background="#303030" > <TextView android:id="@+id/sort_key" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginLeft="10dip" android:textColor="#ffffff" android:textSize="13sp" /> </LinearLayout> <LinearLayout android:id="@+id/name_layout" android:layout_width="fill_parent" android:layout_height="50dip" > <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginLeft="10dip" android:layout_marginRight="10dip" android:src="@drawable/icon" /> <TextView android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:textColor="#ffffff" android:textSize="22sp" /> </LinearLayout></LinearLayout>
In this layout file, the group layout is put in the same way as the previous layout, because not only the interface header needs to display the group, the Group layout must be displayed before the first element in each group. Then add a simple linearlayout that contains an imageview used to display the contact profile and a textview used to display the contact name.
In this way, all the layout files are completed. The following describes how to implement the functions.
First, create a contact object class from the simple start:
Public class contact {/*** contact name */private string name;/*** sort letter */private string sortkey; Public String getname () {return name ;} public void setname (string name) {This. name = Name;} Public String getsortkey () {return sortkey;} public void setsortkey (string sortkey) {This. sortkey = sortkey ;}}
This entity class contains only the contact name and sort key.
Next, write the contact list adapter, create a contactadapter class that inherits from arrayadapter, and add the following code:
Public class contactadapter extends arrayadapter <contact> {/*** layout file of the item to be rendered */private int resource;/*** alphabet grouping tool */private sectionindexer mindexer; public contactadapter (context, int textviewresourceid, list <contact> objects) {super (context, textviewresourceid, objects); resource = textviewresourceid;} @ overridepublic view getview (INT position, view convertview, viewgroup parent) {contact C Ontact = getitem (position); linearlayout layout = NULL; If (convertview = NULL) {layout = (linearlayout) layoutinflater. from (getcontext ()). inflate (resource, null);} else {layout = (linearlayout) convertview;} textview name = (textview) layout. findviewbyid (R. id. name); linearlayout sortkeylayout = (linearlayout) layout. findviewbyid (R. id. sort_key_layout); textview sortkey = (textview) layout. findviewbyid (R. id. sort_key); Name. settext (contact. getname (); int section = mindexer. getsectionforposition (position); If (position = mindexer. getpositionforsection (section) {sortkey. settext (contact. getsortkey (); sortkeylayout. setvisibility (view. visible);} else {sortkeylayout. setvisibility (view. gone);} return layout;}/*** input a grouping tool to the current adapter. ** @ Param indexer */Public void setindexer (sectionindexer indexer) {mindexer = indexer ;}}
In the above Code, the most important thing is the getview method. In this method, we use the getsectionforposition method of sectionindexer to get the corresponding section value through the current position value, then, call the getpositionforsection method through the section value you just obtained to retrieve the new position value. If the current position value and the new position value are equal, we can think that the current position item is the first element in a group. We should display the group layout, in other cases, the Group layout should be hidden.
Finally, let's write the main interface of the program. Open or create a new mainactivity as the main interface of the program. The Code is as follows:
Public class mainactivity extends activity {/*** group Layout */private linearlayout titlelayout;/*** the letter displayed on the Group */private textview title; /* Contact listview */private listview contactslistview;/* contact list adapter */private contactadapter adapter;/* used for alphabet grouping */private alphabetindexer indexer; /*** store contacts on all mobile phones */private list <contact> contacts = new arraylist <contact> ();/*** define the sorting rule of the alphabet */private string alphab ET = "# abcdefghijklmnopqrstuvwxyz";/*** the first visible element used for record identification during scrolling. */Private int lastfirstvisibleitem =-1; @ overrideprotected void oncreate (bundle savedinstancestate) {super. oncreate (savedinstancestate); setcontentview (R. layout. activity_main); adapter = new contactadapter (this, R. layout. contact_item, contacts); titlelayout = (linearlayout) findviewbyid (R. id. title_layout); Title = (textview) findviewbyid (R. id. title); contactslistview = (listview) findviewbyid (R. id. cont Acts_list_view); Uri uri = contactscontract. commondatakinds. phone. content_uri; cursor = getcontentresolver (). query (Uri, new string [] {"display_name", "sort_key"}, null, null, "sort_key"); If (cursor. movetofirst () {do {string name = cursor. getstring (0); string sortkey = getsortkey (cursor. getstring (1); contact = new contact (); contact. setname (name); contact. setsortkey (sortkey); contacts. ad D (contact);} while (cursor. movetonext ();} startmanagingcursor (cursor); indexer = new alphabetindexer (cursor, 1, alphabet); adapter. setindexer (Indexer); If (contacts. size ()> 0) {setupcontactslistview () ;}/ *** sets a listener event for the contact listview, and changes the display position of the group based on the current slide status, to achieve the effect of extrusion animation. */Private void setupcontactslistview () {contactslistview. setadapter (adapter); contactslistview. listener (New onscrolllistener () {@ overridepublic void onscrollstatechanged (abslistview view, int scrollstate) {}@ overridepublic void onscroll (abslistview view, int cursor, int visibleitemcount, int totalitemcount) {int section = indexer. getsectionforposition (firstvisibleitem); int nexts Ecposition = indexer. getpositionforsection (section + 1); If (firstvisibleitem! = Lastfirstvisibleitem) {marginlayoutparams Params = (marginlayoutparams) titlelayout. getlayoutparams (); Params. topmargin = 0; titlelayout. setlayoutparams (Params); title. settext (string. valueof (alphabet. charat (section);} If (nextsecposition = firstvisibleitem + 1) {view childview = view. getchildat (0); If (childview! = NULL) {int titleheight = titlelayout. getheight (); int Bottom = childview. getbottom (); marginlayoutparams Params = (marginlayoutparams) titlelayout. getlayoutparams (); If (bottom <titleheight) {float pusheddistance = bottom-titleheight; Params. topmargin = (INT) pusheddistance; titlelayout. setlayoutparams (Params);} else {If (Params. topmargin! = 0) {Params. topmargin = 0; titlelayout. setlayoutparams (Params) ;}}} lastfirstvisibleitem = firstvisibleitem ;}}) ;}/ *** get the first character of the sort key. If it is an English letter, it is returned directly, otherwise, # is returned #. ** @ Param sortkeystring * the sort key read from the database * @ return English letter or # */private string getsortkey (string sortkeystring) {string key = sortkeystring. substring (0, 1 ). touppercase (); If (key. matches ("[A-Z]") {return key;} return "#";}}
We can see that in the oncreate method, we query the contact name and sort key from the system contact database, and then pass the returned cursor in alphabetindexer as the first parameter. Since we checked two columns in total and the sorting key was in the second column, we passed in 1 as the second sortedcolumnindex parameter. In the third alphabet parameter, the "# abcdefghijklmnopqrstuvwxyz" string is input here, because some contact names may not be within the alphabet, and we use # to represent these contacts.
Then, we listened to the listview scrolling in the setupcontactslistview method. In the onscroll method, we obtained the group value of the first visible element through the getsectionforposition method, and then added 1 to the group value, then, use the getpositionforsection method or the first element in the next group. If the first element value of the next group is equal to the value of the first visible element, add 1, it indicates that the layout of the next group must be different from that of the group on the top of the interface. Then, use the getchildat (0) method of listview to obtain the first child view displayed on the interface, and then use the view. getbottom obtains the position at the bottom of the parent window and compares the height of the group layout to vertical offset the group layout on the top to achieve the extrusion animation effect.
Finally, the androidmanifest. XML code is provided. to read the mobile phone contact, you must add the Android. Permission. read_contacts statement:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.contactsdemo" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="8" /> <uses-permission android:name="android.permission.READ_CONTACTS"></uses-permission> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@android:style/Theme.NoTitleBar" > <activity android:name="com.example.contactsdemo.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application></manifest>
Now let's run the program, as shown in the following figure:
At present, the group navigation and extrusion animation effects have been completed, and it looks quite good. In the next article, I will guide you to continue to improve this program and add the alphabet quick scrolling function, if you are interested, please continue to read the full special effects (lower) of contacts in the Android system to quickly scroll the alphabet.
Now, today's explanation is over. If you have any questions, please leave a message below.
Click here to download the source code