PinnedSectionListView具体下载地址、使用方法和注意事项:http://www.cnblogs.com/zzw1994/p/4997601.html
怎么根据联系人姓名首字符顺序读取联系人:http://www.cnblogs.com/zzw1994/p/4998524.html
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 > 6 7 <com.zzw.contacts.PinnedSectionListView 8 android:id="@+id/listView" 9 android:layout_width="match_parent"10 android:layout_height="match_parent" />11 12 </RelativeLayout>
权限:
<!-- 写权限 --> <uses-permission android:name="android.permission.WRITE_CONTACTS" /> <!-- 读权限 --> <uses-permission android:name="android.permission.READ_CONTACTS" /> <!-- 打电话权限 --> <uses-permission android:name="android.permission.CALL_PHONE" />
主要实现代码:
1 package com.zzw.contacts; 2 3 import java.util.ArrayList; 4 5 import com.zzw.contacts.PinnedSectionListView.PinnedSectionListAdapter; 6 7 import android.app.Activity; 8 import android.content.ContentResolver; 9 import android.content.Context; 10 import android.content.Intent; 11 import android.database.Cursor; 12 import android.graphics.Color; 13 import android.net.Uri; 14 import android.os.Bundle; 15 import android.provider.ContactsContract; 16 import android.view.LayoutInflater; 17 import android.view.View; 18 import android.view.ViewGroup; 19 import android.widget.AdapterView; 20 import android.widget.AdapterView.OnItemClickListener; 21 import android.widget.ArrayAdapter; 22 import android.widget.TextView; 23 24 public class MainActivity extends Activity { 25 26 @Override 27 protected void onCreate(Bundle savedInstanceState) { 28 super.onCreate(savedInstanceState); 29 setContentView(R.layout.activity_main); 30 31 ArrayList<Contact> contacts = new ArrayList<Contact>(); 32 readContacts(contacts); 33 34 final ArrayList<Item> items = new ArrayList<Item>(); 35 36 // 从字母A开始到Z。26个字母,遍历联系人中的首字符是否相等。 37 // 相等则归入一组。 38 int A = (int) 'A'; 39 for (int i = 0; i < 26; i++) { 40 int letter = A + i; 41 char c = (char) letter; 42 43 Item group = new Item(); 44 group.type = Item.GROUP; 45 group.text = c + ""; 46 items.add(group); 47 48 for (int j = 0; j < contacts.size(); j++) { 49 Contact contact = contacts.get(j); 50 String s = contact.firstLetterOfName(); 51 if (s.equals(group.text)) { 52 Item child = new Item(); 53 child.type = Item.CHILD; 54 child.text = contact.name + " " + contact.getPhoneNumbers(); 55 child.contact = contact; 56 items.add(child); 57 } 58 } 59 } 60 61 PinnedSectionListView listView = (PinnedSectionListView) findViewById(R.id.listView); 62 63 ArrayAdapter<Item> adapter = new MyAdapter(this, -1, items); 64 listView.setAdapter(adapter); 65 66 listView.setOnItemClickListener(new OnItemClickListener() { 67 68 @Override 69 public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 70 Item item = items.get(position); 71 72 if (item.type == Item.CHILD) { 73 Contact contact = item.contact; 74 // 简单演示期间,我们只选择第一个电话(不管有几个电话)。 75 String number = contact.phoneNumbers.get(0); 76 if (!number.equals("")) { 77 // 拨打电话 78 Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + number)); 79 startActivity(intent); 80 } 81 } 82 } 83 }); 84 85 } 86 87 private class MyAdapter extends ArrayAdapter<Item>implements PinnedSectionListAdapter { 88 89 private LayoutInflater inflater; 90 private ArrayList<Item> items; 91 92 public MyAdapter(Context context, int resource, ArrayList<Item> items) { 93 super(context, resource, items); 94 this.items = items; 95 inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); 96 } 97 98 @Override 99 public int getCount() {100 return items.size();101 }102 103 @Override104 public int getItemViewType(int position) {105 106 return items.get(position).type;107 }108 109 @Override110 public int getViewTypeCount() {111 112 return 2;113 }114 115 @Override116 public Item getItem(int position) {117 return items.get(position);118 }119 120 @Override121 public View getView(int position, View convertView, ViewGroup parent) {122 123 String text = getItem(position).text;124 125 switch (getItemViewType(position)) {126 case Item.GROUP:127 128 if (convertView == null) {129 convertView = inflater.inflate(android.R.layout.simple_list_item_1, null);130 }131 132 TextView text1 = (TextView) convertView.findViewById(android.R.id.text1);133 134 // 首字符,分组的依据135 text1.setText(text);136 text1.setBackgroundColor(Color.GRAY);137 138 break;139 140 case Item.CHILD:141 if (convertView == null) {142 convertView = inflater.inflate(android.R.layout.simple_list_item_2, null);143 }144 145 TextView text2 = (TextView) convertView.findViewById(android.R.id.text2);146 text2.setText(text);147 148 break;149 }150 return convertView;151 }152 153 // 假设此方法返回皆为false。那么PinnedSectionListView将退化成为一个基础的ListView.154 // 只不过退化后的ListView只是一个拥有两个View Type的ListView。155 // 从某种角度上讲,此方法对于PinnedSectionListView至关重要,因为返回值true或false,156 // 将直接导致PinnedSectionListView是一个PinnedSectionListView,还是一个普通的ListView。157 @Override158 public boolean isItemViewTypePinned(int viewType) {159 boolean type = false;160 switch (viewType) {161 case Item.GROUP:162 type = true;163 break;164 165 case Item.CHILD:166 type = false;167 break;168 169 default:170 type = false;171 break;172 }173 return type;174 }175 176 }177 178 // 读取设备联系人的一般方法。大致流程就是这样,模板化的操作代码。179 private void readContacts(ArrayList<Contact> contacts) {180 Uri uri = Uri.parse("content://com.android.contacts/contacts");181 ContentResolver resolver = this.getContentResolver();182 183 // 在这里我们给query传递进去一个SORT_KEY_PRIMARY184 // 告诉ContentResolver获得的结果按照联系人名字的首字母有序排序185 Cursor cursor = resolver.query(uri, null, null, null,186 android.provider.ContactsContract.Contacts.SORT_KEY_PRIMARY);187 188 while (cursor.moveToNext()) {189 // 联系人id190 String id = cursor.getString(cursor.getColumnIndex(android.provider.ContactsContract.Contacts._ID));191 // Sort key,读取的联系人按照姓名从 A->Z 的排序分组192 String sork_key_primary = cursor193 .getString(cursor.getColumnIndex(android.provider.ContactsContract.Contacts.SORT_KEY_PRIMARY));194 // 获取联系人姓名195 String name = cursor196 .getString(cursor.getColumnIndex(android.provider.ContactsContract.Contacts.DISPLAY_NAME));197 198 Contact mContact = new Contact();199 mContact.id = id;200 mContact.sort_key_primay = sork_key_primary;201 mContact.name = name;202 203 // 获取联系人的手机号码204 Cursor phone = resolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,205 ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "=" + id, null, null);206 // 取得电话号码(可能存在多个号码)207 // 因为在同一个名字下,用户可能存有一个以上号码208 // 遍历209 ArrayList<String> phoneNumbers = new ArrayList<String>();210 while (phone.moveToNext()) {211 int phoneFieldColumnIndex = phone.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);212 String phoneNumber = phone.getString(phoneFieldColumnIndex);213 phoneNumbers.add(phoneNumber);214 }215 216 mContact.phoneNumbers = phoneNumbers;217 contacts.add(mContact);218 }219 }220 221 // 用于承载数据块的类。222 // 字段分为类型(type)和值(text)。223 private class Item {224 public static final int GROUP = 0;225 public static final int CHILD = 1;226 227 public int type;228 public String text;229 230 public Contact contact = null;231 }232 233 // 用于装载从联系人数据库中读取到的数据。234 // 结构化数据,便于数据操作和访问。235 private class Contact {236 public String id;237 public String name;238 public String sort_key_primay;239 public ArrayList<String> phoneNumbers;240 241 // 获得一个联系人名字的首字母。242 // 比如一个人的名字叫做“安卓”,那么这个人的首字母是:A243 public String firstLetterOfName() {244 String s = sort_key_primay.charAt(0) + "";245 246 return s.toUpperCase();247 }248 249 public String getPhoneNumbers() {250 String phones = "";251 for (int i = 0; i < phoneNumbers.size(); i++) {252 phones += ": " + phoneNumbers.get(i);253 }254 return phones;255 }256 }257 }