Android 获取手机通讯录信息 — 头像、姓名和A-Z的快速查询

 首先先看一下效果图再说吧:

具体实现过程如下:

先在AndroidManifest.xml文件中添加读取联系人的权限:

1     <uses-permission android:name="android.permission.READ_CONTACTS" />

联系人列表对应的适配器:

 1 package com.example.testcontacts.adapter;
 2 
 3 import java.util.List;
 4 
 5 import android.content.Context;
 6 import android.view.View;
 7 import android.view.ViewGroup;
 8 import android.widget.ArrayAdapter;
 9 import android.widget.LinearLayout;
10 import android.widget.SectionIndexer;
11 import android.widget.TextView;
12 
13 import com.example.testcontacts.R;
14 import com.example.testcontacts.domain.Contact;
15 
16 public class ContactAdapter extends ArrayAdapter<Contact> {
17     private int resource;// 需要渲染的item布局文件
18     private SectionIndexer mIndexer;// 字母表分组工具
19 
20     public ContactAdapter(Context context, int textViewResourceId,List<Contact> objects) {
21         super(context, textViewResourceId, objects);
22         resource = textViewResourceId;
23     }
24 
25     @Override
26     public View getView(int position, View convertView, ViewGroup parent) {
27         Contact contact = getItem(position);
28         View view = convertView == null ? View.inflate(getContext(),  R.layout.contact_item, null) : convertView;
29         LinearLayout ll_sort_key = (LinearLayout) view.findViewById(R.id.ll_sort_key);
30         TextView tv_sort_key = (TextView) view.findViewById(R.id.tv_sort_key);
31         TextView tv_name = (TextView) view.findViewById(R.id.tv_name);
32         TextView tv_number = (TextView) view.findViewById(R.id.tv_number);
33 
34         tv_name.setText(contact.getName());
35         tv_number.setText(contact.getNumber());
36         
37         int section = mIndexer.getSectionForPosition(position);
38         if (position == mIndexer.getPositionForSection(section)) {
39             tv_sort_key.setText(contact.getSortKey());
40             ll_sort_key.setVisibility(View.VISIBLE);
41         }else{
42             ll_sort_key.setVisibility(View.GONE);
43         }
44         return view;
45     }
46     
47     /**给当前适配器传入一个分组工具*/
48     public void setIndexer(SectionIndexer indexer) {  
49         mIndexer = indexer;
50     }
51 }

实体类:

 1 package com.example.testcontacts.domain;
 2 
 3 public class Contact {
 4     private String name;// 联系人姓名
 5     private String sortKey;// 排序字母
 6     private String number;
 7 
 8     public String getName() {
 9         return name;
10     }
11 
12     public void setName(String name) {
13         this.name = name;
14     }
15 
16     public String getSortKey() {
17         return sortKey;
18     }
19 
20     public void setSortKey(String sortKey) {
21         this.sortKey = sortKey;
22     }
23 
24     public String getNumber() {
25         return number;
26     }
27 
28     public void setNumber(String number) {
29         this.number = number;
30     }
31 }

java类:

  1 package com.example.testcontacts;
  2 
  3 import java.util.ArrayList;
  4 import java.util.List;
  5 
  6 import android.app.Activity;
  7 import android.database.Cursor;
  8 import android.net.Uri;
  9 import android.os.Bundle;
 10 import android.provider.ContactsContract;
 11 import android.view.MotionEvent;
 12 import android.view.View;
 13 import android.view.View.OnTouchListener;
 14 import android.view.ViewGroup.MarginLayoutParams;
 15 import android.widget.AbsListView;
 16 import android.widget.AbsListView.OnScrollListener;
 17 import android.widget.AlphabetIndexer;
 18 import android.widget.Button;
 19 import android.widget.LinearLayout;
 20 import android.widget.ListView;
 21 import android.widget.RelativeLayout;
 22 import android.widget.TextView;
 23 
 24 import com.example.testcontacts.adapter.ContactAdapter;
 25 import com.example.testcontacts.domain.Contact;
 26 
 27 public class MainActivity extends Activity {
 28     private LinearLayout ll_title;// 分组的布局
 29     private RelativeLayout rl_toast;
 30     private Button btn_alphabet;
 31     private TextView tv_title; // 分组上显示的字母
 32     private TextView tv_toast;
 33     private ListView lv_contacts;// 联系人ListView
 34 
 35     private ContactAdapter adapter;// 联系人列表适配器
 36     private AlphabetIndexer indexer;// 用于进行字母表分组
 37     private List<Contact> contacts = new ArrayList<Contact>();// 存储所有手机中的联系人
 38     private String alphabet = "#ABCDEFGHIJKLMNOPQRSTUVWXYZ";// 定义字母表的排序规则
 39     private int lastFirstVisibleItem = -1;// 上次第一个可见元素,用于滚动时记录标识。
 40 
 41     @Override
 42     protected void onCreate(Bundle savedInstanceState) {
 43         super.onCreate(savedInstanceState);
 44         setContentView(R.layout.activity_main);
 45 
 46         adapter = new ContactAdapter(this, R.layout.contact_item, contacts);
 47         ll_title = (LinearLayout) findViewById(R.id.ll_title);
 48         rl_toast = (RelativeLayout) findViewById(R.id.rl_section_toast);
 49         tv_title = (TextView) findViewById(R.id.tv_title);
 50         tv_toast = (TextView) findViewById(R.id.tv_section_toast);
 51         btn_alphabet = (Button) findViewById(R.id.btn_alphabet);
 52         lv_contacts = (ListView) findViewById(R.id.lv_contacts);
 53 
 54         Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
 55         Cursor cursor = getContentResolver().query(uri,
 56                 new String[] { "display_name", "sort_key", }, null, null,
 57                 "sort_key");
 58         if (cursor.moveToFirst()) {
 59             do {
 60                 String name = cursor.getString(0);
 61                 String sortKey = getSortKey(cursor.getString(1));
 62                 Contact contact = new Contact();
 63                 contact.setName(name);
 64                 contact.setSortKey(sortKey);
 65                 contacts.add(contact);
 66             } while (cursor.moveToNext());
 67         }
 68         startManagingCursor(cursor);
 69         indexer = new AlphabetIndexer(cursor, 1, alphabet);
 70         adapter.setIndexer(indexer);
 71         if (contacts.size() > 0) {
 72              setListViewListener();
 73              setAlpabetListener();
 74         }
 75     }
 76 
 77     /** 根据当前的滑动状态来改变分组的显示位置,从而实现挤压动画的效果 */
 78     private void setListViewListener() {
 79         lv_contacts.setAdapter(adapter);
 80         lv_contacts.setOnScrollListener(new OnScrollListener() {
 81             @Override
 82             public void onScrollStateChanged(AbsListView view, int scrollState) {
 83             }
 84 
 85             @Override
 86             public void onScroll(AbsListView view, int firstVisibleItem,
 87                     int visibleItemCount, int totalItemCount) {
 88                 int section = indexer.getSectionForPosition(firstVisibleItem);//当前分组所在的位置
 89                 int nextSecPosition = indexer.getPositionForSection(section + 1);//找出当前位置所在的分组
 90                 if (firstVisibleItem != lastFirstVisibleItem) {
 91                     MarginLayoutParams params = (MarginLayoutParams) ll_title
 92                             .getLayoutParams();
 93                     params.topMargin = 0;
 94                     ll_title.setLayoutParams(params);
 95                     tv_title.setText(String.valueOf(alphabet.charAt(section)));
 96                 }
 97                 if (nextSecPosition == firstVisibleItem + 1) {
 98                     View childView = view.getChildAt(0);
 99                     if (childView != null) {
100                         int titleHeight = ll_title.getHeight();
101                         int bottom = childView.getBottom();
102                         MarginLayoutParams params = (MarginLayoutParams) ll_title
103                                 .getLayoutParams();
104                         if (bottom < titleHeight) {
105                             float pushedDistance = bottom - titleHeight;
106                             params.topMargin = (int) pushedDistance;
107                             ll_title.setLayoutParams(params);
108                         } else {
109                             if (params.topMargin != 0) {
110                                 params.topMargin = 0;
111                                 ll_title.setLayoutParams(params);
112                             }
113                         }
114                     }
115                 }
116                 lastFirstVisibleItem = firstVisibleItem;
117             }
118         });
119     }
120 
121     /**
122      * 获取sort key的首个字符,如果是英文字母就直接返回,否则返回#。
123      * @param sortKeyString 数据库中读取出的sort key
124      * @return 英文字母或者#
125      */
126     private String getSortKey(String sortKeyString) {
127         String key = sortKeyString.substring(0, 1).toUpperCase();
128         if (key.matches("[A-Z]")) {
129             return key;
130         }
131         return "#";
132     }
133 
134     /**
135      * 设置字母表上的触摸事件,根据当前触摸的位置结合字母表的高度,计算出当前触摸在哪个字母上。 
136      * 当手指按在字母表上时,展示弹出式分组。手指离开字母表时,将弹出式分组隐藏。
137      */
138     private void setAlpabetListener() {
139         btn_alphabet.setOnTouchListener(new OnTouchListener() {
140             @Override
141             public boolean onTouch(View v, MotionEvent event) {
142                 float alphabetHeight = btn_alphabet.getHeight();//获得字母表的总高度
143                 float y = event.getY();//获取到目前手指在字母表上的纵坐标
144                 int sectionPosition = (int) ((y/alphabetHeight)/(1f/27f));//当前手指所在位置(0表在#端,1表示在Z端)。
145                 if (sectionPosition < 0) {
146                     sectionPosition = 0;
147                 } else if (sectionPosition > 26) {
148                     sectionPosition = 26;
149                 }
150                 String sectionLetter = String.valueOf(alphabet.charAt(sectionPosition));
151                 int position = indexer.getPositionForSection(sectionPosition);
152                 switch (event.getAction()) {
153                 case MotionEvent.ACTION_DOWN://在弹出式分组上显示当前手指所按的字母
154                     btn_alphabet.setBackgroundResource(R.drawable.contact_list_scroll_pressed);
155                     rl_toast.setVisibility(View.VISIBLE);
156                     tv_toast.setText(sectionLetter);
157                     lv_contacts.setSelection(position);//把列表滚动到相应的分组
158                     break;
159                 case MotionEvent.ACTION_MOVE://同ACTION_DOWN
160                     tv_toast.setText(sectionLetter);
161                     lv_contacts.setSelection(position);
162                     break;
163                 default://弹出式分组布局隐藏
164                     btn_alphabet.setBackgroundResource(R.drawable.contact_list_scroll_normal);
165                     rl_toast.setVisibility(View.GONE);
166                 }
167                 return true;
168             }
169         });
170     }
171 }

样式:

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <shape xmlns:android="http://schemas.android.com/apk/res/android" >
 3 
 4     <corners
 5         android:bottomLeftRadius="0dp"
 6         android:bottomRightRadius="0dp"
 7         android:topLeftRadius="0dp"
 8         android:topRightRadius="0dp" />
 9 
10     <gradient
11         android:angle="90"
12         android:endColor="#8BC4DF"
13         android:startColor="#8BC4DF" />
14 
15     <stroke android:width="1dp" />
16 
17 </shape>

布局文件:

在res/layout中新建一个布局文件,起名为:activity.main.xml

 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:orientation="vertical" >
 6 
 7     <ListView
 8         android:id="@+id/lv_contacts"
 9         android:layout_width="fill_parent"
10         android:layout_height="wrap_content"
11         android:layout_alignParentTop="true"
12         android:divider="@drawable/divider1"
13         android:dividerHeight="1dp"
14         android:fadingEdge="none"
15         android:scrollbars="none" >
16     </ListView>
17 
18     <LinearLayout
19         android:id="@+id/ll_title"
20         android:layout_width="fill_parent"
21         android:layout_height="18dp"
22         android:layout_alignParentTop="true"
23         android:background="@drawable/itembg" >
24 
25         <TextView
26             android:id="@+id/tv_title"
27             android:layout_width="wrap_content"
28             android:layout_height="wrap_content"
29             android:layout_gravity="center_horizontal"
30             android:layout_marginLeft="10dp"
31             android:textColor="#000000"
32             android:textSize="14sp" />
33     </LinearLayout>
34 
35     <Button
36         android:id="@+id/btn_alphabet"
37         android:layout_width="wrap_content"
38         android:layout_height="fill_parent"
39         android:layout_alignParentRight="true"
40         android:background="@drawable/contact_list_scroll_normal" />
41 
42     <RelativeLayout
43         android:id="@+id/rl_section_toast"
44         android:layout_width="70dp"
45         android:layout_height="70dp"
46         android:layout_centerInParent="true"
47         android:background="@drawable/section_toast"
48         android:visibility="gone" >
49 
50         <TextView
51             android:id="@+id/tv_section_toast"
52             android:layout_width="wrap_content"
53             android:layout_height="wrap_content"
54             android:layout_centerInParent="true"
55             android:textColor="#000"
56             android:textSize="30sp" />
57     </RelativeLayout>
58 
59 </RelativeLayout>

在res/layout中新建一个布局文件,起名为:contact_item.xml

 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     android:layout_width="match_parent"
 3     android:layout_height="match_parent"
 4     android:orientation="vertical" >
 5 
 6     <LinearLayout
 7         android:id="@+id/ll_sort_key"
 8         android:layout_width="fill_parent"
 9         android:layout_height="18dip"
10         android:background="@drawable/itembg" >
11 
12         <TextView
13             android:id="@+id/tv_sort_key"
14             android:layout_width="wrap_content"
15             android:layout_height="wrap_content"
16             android:layout_gravity="center_horizontal"
17             android:layout_marginLeft="10dip"
18             android:text="A"
19             android:textColor="#000000"
20             android:textSize="14sp" />
21     </LinearLayout>
22 
23     <LinearLayout
24         android:id="@+id/ll_name"
25         android:layout_width="fill_parent"
26         android:layout_height="50dip" >
27 
28         <ImageView
29             android:layout_width="40dp"
30             android:layout_height="40dp"
31             android:layout_gravity="center_vertical"
32             android:layout_marginLeft="10dip"
33             android:layout_marginRight="10dip"
34             android:src="@drawable/icon" />
35 
36         <LinearLayout
37             android:layout_width="fill_parent"
38             android:layout_height="fill_parent"
39             android:layout_gravity="top"
40             android:orientation="vertical" >
41 
42             <TextView
43                 android:id="@+id/tv_name"
44                 android:layout_width="wrap_content"
45                 android:layout_height="wrap_content"
46                 android:layout_gravity="center_vertical"
47                 android:text="张三"
48                 android:textColor="#000000"
49                 android:textSize="18sp" />
50 
51             <TextView
52                 android:id="@+id/tv_number"
53                 android:layout_width="wrap_content"
54                 android:layout_height="wrap_content"
55                 android:layout_gravity="center_vertical"
56                 android:layout_marginTop="10dp"
57                 android:text="186057986"
58                 android:textColor="#88000000"
59                 android:textSize="12sp" />
60         </LinearLayout>
61     </LinearLayout>
62 
63 </LinearLayout>


 

posted on 2014-01-15 16:37  清凉一夏之博客  阅读(3180)  评论(0编辑  收藏  举报