PinnedSectionListView具体下载地址、使用方法和注意事项:http://www.cnblogs.com/zzw1994/p/4997601.html
怎么根据联系人姓名首字符顺序读取联系人:http://www.cnblogs.com/zzw1994/p/4998524.html
<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"
> <com.zzw.contacts.PinnedSectionListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent" /> </RelativeLayout>
activity_main.xml
权限:
<!-- 写权限 -->
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<!-- 读权限 -->
<uses-permission android:name="android.permission.READ_CONTACTS" />
<!-- 打电话权限 -->
<uses-permission android:name="android.permission.CALL_PHONE" />
主要实现代码:
package com.zzw.contacts; import java.util.ArrayList; import com.zzw.contacts.PinnedSectionListView.PinnedSectionListAdapter; import android.app.Activity;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.TextView; public class MainActivity extends Activity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); ArrayList<Contact> contacts = new ArrayList<Contact>();
readContacts(contacts); final ArrayList<Item> items = new ArrayList<Item>(); // 从字母A开始到Z。26个字母,遍历联系人中的首字符是否相等。
// 相等则归入一组。
int A = (int) 'A';
for (int i = 0; i < 26; i++) {
int letter = A + i;
char c = (char) letter; Item group = new Item();
group.type = Item.GROUP;
group.text = c + "";
items.add(group); for (int j = 0; j < contacts.size(); j++) {
Contact contact = contacts.get(j);
String s = contact.firstLetterOfName();
if (s.equals(group.text)) {
Item child = new Item();
child.type = Item.CHILD;
child.text = contact.name + " " + contact.getPhoneNumbers();
child.contact = contact;
items.add(child);
}
}
} PinnedSectionListView listView = (PinnedSectionListView) findViewById(R.id.listView); ArrayAdapter<Item> adapter = new MyAdapter(this, -1, items);
listView.setAdapter(adapter); listView.setOnItemClickListener(new OnItemClickListener() { @Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Item item = items.get(position); if (item.type == Item.CHILD) {
Contact contact = item.contact;
// 简单演示期间,我们只选择第一个电话(不管有几个电话)。
String number = contact.phoneNumbers.get(0);
if (!number.equals("")) {
// 拨打电话
Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + number));
startActivity(intent);
}
}
}
}); } private class MyAdapter extends ArrayAdapter<Item>implements PinnedSectionListAdapter { private LayoutInflater inflater;
private ArrayList<Item> items; public MyAdapter(Context context, int resource, ArrayList<Item> items) {
super(context, resource, items);
this.items = items;
inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
} @Override
public int getCount() {
return items.size();
} @Override
public int getItemViewType(int position) { return items.get(position).type;
} @Override
public int getViewTypeCount() { return 2;
} @Override
public Item getItem(int position) {
return items.get(position);
} @Override
public View getView(int position, View convertView, ViewGroup parent) { String text = getItem(position).text; switch (getItemViewType(position)) {
case Item.GROUP: if (convertView == null) {
convertView = inflater.inflate(android.R.layout.simple_list_item_1, null);
} TextView text1 = (TextView) convertView.findViewById(android.R.id.text1); // 首字符,分组的依据
text1.setText(text);
text1.setBackgroundColor(Color.GRAY); break; case Item.CHILD:
if (convertView == null) {
convertView = inflater.inflate(android.R.layout.simple_list_item_2, null);
} TextView text2 = (TextView) convertView.findViewById(android.R.id.text2);
text2.setText(text); break;
}
return convertView;
} // 假设此方法返回皆为false。那么PinnedSectionListView将退化成为一个基础的ListView.
// 只不过退化后的ListView只是一个拥有两个View Type的ListView。
// 从某种角度上讲,此方法对于PinnedSectionListView至关重要,因为返回值true或false,
// 将直接导致PinnedSectionListView是一个PinnedSectionListView,还是一个普通的ListView。
@Override
public boolean isItemViewTypePinned(int viewType) {
boolean type = false;
switch (viewType) {
case Item.GROUP:
type = true;
break; case Item.CHILD:
type = false;
break; default:
type = false;
break;
}
return type;
} } // 读取设备联系人的一般方法。大致流程就是这样,模板化的操作代码。
private void readContacts(ArrayList<Contact> contacts) {
Uri uri = Uri.parse("content://com.android.contacts/contacts");
ContentResolver resolver = this.getContentResolver(); // 在这里我们给query传递进去一个SORT_KEY_PRIMARY
// 告诉ContentResolver获得的结果按照联系人名字的首字母有序排序
Cursor cursor = resolver.query(uri, null, null, null,
android.provider.ContactsContract.Contacts.SORT_KEY_PRIMARY); while (cursor.moveToNext()) {
// 联系人id
String id = cursor.getString(cursor.getColumnIndex(android.provider.ContactsContract.Contacts._ID));
// Sort key,读取的联系人按照姓名从 A->Z 的排序分组
String sork_key_primary = cursor
.getString(cursor.getColumnIndex(android.provider.ContactsContract.Contacts.SORT_KEY_PRIMARY));
// 获取联系人姓名
String name = cursor
.getString(cursor.getColumnIndex(android.provider.ContactsContract.Contacts.DISPLAY_NAME)); Contact mContact = new Contact();
mContact.id = id;
mContact.sort_key_primay = sork_key_primary;
mContact.name = name; // 获取联系人的手机号码
Cursor phone = resolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "=" + id, null, null);
// 取得电话号码(可能存在多个号码)
// 因为在同一个名字下,用户可能存有一个以上号码
// 遍历
ArrayList<String> phoneNumbers = new ArrayList<String>();
while (phone.moveToNext()) {
int phoneFieldColumnIndex = phone.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
String phoneNumber = phone.getString(phoneFieldColumnIndex);
phoneNumbers.add(phoneNumber);
} mContact.phoneNumbers = phoneNumbers;
contacts.add(mContact);
}
} // 用于承载数据块的类。
// 字段分为类型(type)和值(text)。
private class Item {
public static final int GROUP = 0;
public static final int CHILD = 1; public int type;
public String text; public Contact contact = null;
} // 用于装载从联系人数据库中读取到的数据。
// 结构化数据,便于数据操作和访问。
private class Contact {
public String id;
public String name;
public String sort_key_primay;
public ArrayList<String> phoneNumbers; // 获得一个联系人名字的首字母。
// 比如一个人的名字叫做“安卓”,那么这个人的首字母是:A
public String firstLetterOfName() {
String s = sort_key_primay.charAt(0) + ""; return s.toUpperCase();
} public String getPhoneNumbers() {
String phones = "";
for (int i = 0; i < phoneNumbers.size(); i++) {
phones += ": " + phoneNumbers.get(i);
}
return phones;
}
}
}
基于PinnedSectionListView实现联系人通讯录并且点击打电话的更多相关文章
-
【WP8.1开发】基于应用的联系人存储
上一篇文章所吹的牛是访问系统(手机)上的联系人,当然那只是读不能改,这是自然的,要是让你能随便修改用户的联系人信息的话,那后果很严重,有些恶意开发者就有可能把”你的户口改成猪“. 但是,API也允许应 ...
-
Android软件开发之获取通讯录联系人信息
Android手机的通讯录联系人全部都存在系统的数据库中,如果须要获得通讯里联系人的信息就须要访问系统的数据库,才能将信息拿出来. 这一篇文章我主要带领同学们熟悉Android的通讯录机制. 图中选中 ...
-
Swift - 访问通讯录联系人(使用系统提供的通讯录交互界面)
1,通讯录访问介绍 通讯录(或叫地址簿,电话簿)是一个数据库,里面储存了联系人的相关信息.要实现访问通讯录有如下两种方式: (1)AddressBook.framework框架 : 没有界面,通过代码 ...
-
iOS获取通讯录所有联系人信息
以下是2种方式: 第一种方法: GetAddressBook.h #import <Foundation/Foundation.h> @interface GetAddressBook : ...
-
Android6.0运行时权限(基于RxPermission开源库)
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 在6.0以前的系统,都是权限一刀切的处理方式,只要用户安装,Manifest申请的权限都会被赋予,并且安装后权限也撤销不了. And ...
-
计算机网络课设之TCP通讯录
这篇文章我主要是想对这学期末计算机网络课程设计所做的一个小项目也就是基于tcp协议的通讯录做一个总结梳理.项目的具体的代码实现是基于C语言,当然在此之前网上也有一些基于c++编写的tcp通讯录,原理都 ...
-
Swift - 访问通讯录-使用AddressBook.framework和AddressBookUI.framework框架实现
1,通讯录访问介绍 通讯录(或叫地址簿,电话簿)是一个数据库,里面储存了联系人的相关信息.要实现访问通讯录有如下两种方式: (1)AddressBook.framework框架 : 没有界面,通过代码 ...
-
iOS获取通讯录 电话号码与姓名
// 还是导入 #import <AddressBook/AddressBook.h> - (void)fetchAddressBookBeforeIOS9{ ABAddressBookR ...
-
Jquery Mobile设计Android通讯录第二章
本文是jQuery Mobile设计Android通讯录系统教程的第二篇,在上一篇教程中(http://publish.itpub.net/a2011/0517/1191/000001191561.s ...
随机推荐
-
Android测试提升效率批处理脚本
前言: APP测试过程中,经常需要用的一些命令,如adb,每次敲命令,虽可以加深印象,但个人认为那即繁琐又浪费时间.本文贴出一些我使用的批处理,以及一点点小小技巧. 目录 1.[查看APK文件信息.b ...
-
ios10 safari 的坑!
| 导语 ios10 的safari,又给前端开发者挖坑了..测试验证此问题只出现在ios10 safari中.想早点知道结论的,可以直接看最后一个结论~因为,解决过程不重要! 个人原创,未经允许,禁 ...
-
仿各种APP将文章DOM转JSON并在APP中以列表显示(android、ios、php已开源)
背景 一直以来都想实现类似新闻客户端.鲜城等文章型app的正文显示,即在web editor下编辑后存为json,在app中解析json并显示正文. 网上搜过,没找到*.都是给的思路,然后告知是公司 ...
-
居于集成了adt的Android 开发环境配置
一.先说一下环境 Windows 8.1 64 位 注:win7 Ultimate 64 配置会出现 Android SDK manger 不能启动的问题,是因为android.bat 里调用了fi ...
-
【Qt】Qt国际化【转】
简介 Qt国际化属于Qt高级中的一部分,本想着放到后面来说,上节刚好介绍了Qt Linguist,趁热打铁就一起了解下. 对于绝大多数的应用程序,在刚启动时,需要加载默认的语言(或最后一次设置的语言) ...
-
Spring使用小结2
之前做过不少spring想过知识点内容的摘录, Spring框架的特点.模块组成.优缺点 spring相关的bean管理想过知识点及依赖注入方式 今天说下近端时间中项目中遇到的相关印象比较深的知识点 ...
-
利用proxychains在终端使用socks5代理
最近用各种脚本下载东西的时候发现有的站点需要当地IP才能下,比如.....nico, youtube等: 所以就找了下能在终端用socks5代理的工具,最后找到了proxychains,从此再无压力= ...
-
iOS下JS与OC互相调用(三)--MessageHandler
使用WKWebView的时候,如果想要实现JS调用OC方法,除了拦截URL之外,还有一种简单的方式.那就是利用WKWebView的新特性MessageHandler来实现JS调用原生方法. Messa ...
-
Java spring boot 2.0连接mysql异常:The server time zone value &#39;&#214;&#208;&#185;&#250;&#177;&#234;&#215;&#188;&#202;&#177;&#188;&#228;&#39; is unrecognized or represents more than one time zone
解决办法:application.yml提示信息表明数据库驱动com.mysql.jdbc.Driver'已经被弃用了.应当使用新的驱动com.mysql.cj.jdbc.Driver' com.my ...
-
curl -d中的json存在引号怎么处理?
1\将其改写为I'\''m就可以执行 2\ curl -u elastic:mypass -X GET "localhost:9200/_analyze?pretty" -d 'a ...