一、跳转系统通讯录

普通的联系人列表,无法选择联系人或回调,只能查看详情

             Intent intent = new Intent();intent.setClassName("com.android.contacts","com.android.contacts.activities.PeopleActivity");startActivity(intent);

二、选择联系人回调结果

跳转至选择联系人列表:

             Intent intent = new Intent();intent.setAction(Intent.ACTION_PICK);// intent.setData(Contacts.People.CONTENT_URI);intent.setData(ContactsContract.Contacts.CONTENT_URI);startActivityForResult(intent, 100);

回调结果处理:

@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {// TODO Auto-generated method stubsuper.onActivityResult(requestCode, resultCode, data);if (requestCode == 100 && resultCode == RESULT_OK) {Log.i("TAG", "回调开始");Uri data2 = data.getData();// content://contacts/people/2Cursor cursor = getContentResolver().query(data2, null, null, null,null);if (cursor.moveToFirst()) {String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));Log.i("TAG", "姓名:" + name);Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,ContactsContract.CommonDataKinds.Phone.CONTACT_ID+ " = "+ cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID)),null, null);if (phones.moveToFirst()) {String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));Log.i("TAG", "电话:" + phoneNumber);tv1.setText("姓名:" + name + "\n电话:" + phoneNumber);}phones.close();}cursor.close();}}

友情提醒,到此为止的测试环境都是在GenyMotion模拟器上,在真机上的结果是可能会出现重复的数据

三、自定义联系人界面

getContentResolver获取到的联系人列表,默认是按照创建时间排序,在实际使用中,我们希望按姓名排序,有以下两种方法:

1、使用query方法中的projection参数和sortorder参数来实现排序,比较简单方便

 /*** see http://blog.chinaunix.net/uid-26930580-id-4137246.html* @param listMembers*/public void getAllContact(List<ContactData> listMembers) {Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;Cursor cursor = getContentResolver().query(uri, MYPROJECTION,null, null, Phone.SORT_KEY_PRIMARY);try {if (cursor.moveToFirst()) {do {ContactData contact = new ContactData();String contact_phone = cursor.getString(2);String name = cursor.getString(0);String sortKey = getSortKey(cursor.getString(1));int contact_id = cursor.getInt(3);contact.name = name;contact.sortKey = sortKey;contact.phone = contact_phone;contact.setId(contact_id);if (name != null)listMembers.add(contact);} while (cursor.moveToNext());}} catch (Exception e) {e.printStackTrace();} finally {cursor.close();}}/*** 获取sort key的首个字符,如果是英文字母就直接返回,否则返回#。* * @param sortKeyString*            数据库中读取出的sort key* @return 英文字母或者#*/private static String getSortKey(String sortKeyString) {String key = sortKeyString.substring(0, 1).toUpperCase();if (key.matches("[A-Z]")) {return key;}return "#";}

这里面的ContactData就是自定义的实体类,包括几个常用属性

     public int id;public String name;public String phone;public String sortKey;

A list of which columns to return. Passing null will return all columns, which is inefficient.这是第二个参数projection的解释,其实就是定义要返回list类型,为null就返回所有字段

 private static final String[] MYPROJECTION = new String[] {Phone.DISPLAY_NAME, Phone.SORT_KEY_PRIMARY, Phone.NUMBER,Phone.CONTACT_ID };

备注:由于genymotion模拟器的联系人无法输入中文,所以暂时换成了海马玩模拟器,所以和上面数据不相同

2、其实如果只是模拟器跑应用的话,上面的就够了,但是在真机中还有sim卡中的联系人,如果还用上面那个方法,那么获取的将会是所有的数据,包括手机本地的以及sim卡中的联系人,这样就会有重复的数据,我的解决方法就是先去判断手机的sim卡状态,如果状态良好的话就直接取sim卡的联系人数据,如果取得的sim卡的联系人数据为空,那么再调用上面那个方法获取全部联系人,如果没有sim卡的话,也调用上面那个方法获取全部联系人。

只取sim卡中联系人并进行汉字排序的方法:

 private void getSIMContacts(List<ContactData> listMembers) {ContentResolver resolver = getContentResolver();// 获取Sims卡联系人Uri uri = Uri.parse("content://icc/adn");Cursor phoneCursor = resolver.query(uri, null, null,null, null);try {if (phoneCursor.moveToFirst()) {do {ContactData data = new ContactData();// 得到手机号码String phoneNumber = phoneCursor.getString(1); //在测试机上索引为2,华为荣耀上索引为1// 当手机号码为空的或者为空字段 跳过当前循环if (phoneNumber.equals(" ") || phoneNumber == null)continue;// 得到联系人名称String contactName = phoneCursor.getString(0);//在测试机上索引为1,华为荣耀上索引为0,原因应该是测试机联系人的表结构多了一个自增长的idif (contactName.equals(" ") || contactName == null)continue;data.name = contactName;data.phone = phoneNumber;if (contactName != null)listMembers.add(data);} while (phoneCursor.moveToNext());//中文排序Comparator comp = new Mycomparator();Collections.sort(listMembers, comp);}} catch (Exception e) {e.printStackTrace();} finally {phoneCursor.close();}}//通讯录按中文拼音排序,英文放在最后面class Mycomparator implements Comparator {public int compare(Object o1, Object o2) {ContactData c1 = (ContactData) o1;ContactData c2 = (ContactData) o2;Comparator cmp = Collator.getInstance(java.util.Locale.CHINA);return cmp.compare(c1.name, c2.name);}}

四、后续优化

1、优化了sim卡和手机通讯录联系人重复的处理方法,使用第三步第二小步的方法是有点繁琐,所以这里就使用了先取到所有的联系人数据,然后对list进行去重处理;最关键的地方就是记得重写实体类的equals方法,不然使用list.contains(contactData)时会一直返回false

     @Overridepublic boolean equals(Object obj) {// TODO Auto-generated method stubif (obj instanceof ContactData) {ContactData u = (ContactData) obj;return this.name.equals(u.name) && this.phone.equals(phone)&& this.sortKey.equals(sortKey);}return super.equals(obj);}

list去重的方法其实有很多,这里列举两个高效的,主要是代码简洁不会打乱原有顺序,用set就会出现无序的list了

 List<ContactData> removeDuplicateData(List<ContactData> cList) {List<ContactData> cList2 = new ArrayList<ContactData>();for (ContactData data : cList) {if (Collections.frequency(cList2, data) < 1)cList2.add(data);}return cList2;}List<ContactData> removeDuplicateData2(List<ContactData> cList) {List<ContactData> cList2 = new ArrayList<ContactData>();for (int i = 0; i < cList.size(); i++) {if (!cList2.contains(cList.get(i)))cList2.add(cList.get(i));}return cList2;}

2、上滑下拉字母动画,有这样一个顶的效果,可以参考PinnedHeaderListView

下载了github上的源码,根据他的example稍微该了下adapter,主要还是要自己生成一个list数据传过去,生成通讯录list关键代码如下:

     for (int i = 0; i < cList2.size(); i++) {ParentContactData pData = new ParentContactData();pData.setLetter(cList2.get(i).sortKey);List<ContactData> dList = new ArrayList<ContactListActivity.ContactData>();dList.add(cList2.get(i));while ((i + 1) < cList2.size()&& cList2.get(i + 1).sortKey.equals(cList2.get(i).sortKey)) {dList.add(cList2.get(i + 1));i++;}pData.setChildlist(dList);listData.add(pData);}

主要是首字母的计算,使用了for循环中的while循环进行判断,如果满足条件就添加到之前的字母list中,否则跳出while循环

3、右侧添加sideBar,字母索引,这里面借用了Android 实现ListView的A-Z字母排序和过滤搜索功能,实现汉字转成拼音这篇博文中的SideBar源码,还有一个获取首字母索引的方法

 /*** 根据分类的首字母的Char ascii值获取其第一次出现该首字母的位置* @return 父索引值,即ABCD等的索引0-26*/public int getPositionForSection(int section) {for (int i = 0; i < mListData.size(); i++) {String sortStr = mListData.get(i).getLetter();char firstChar = sortStr.toUpperCase().charAt(0);if (firstChar == section) {return i;}}return -1;}

获取到这个索引值后,在列表界面的代码中还不能直接调用mListView.setSelection()方法,因为上面这个方法返回的索引值只是父列表的索引值,而setSelection方法要的参数是相对于整个Listview的索引值,所以还得再加工计算一下

 public int getAllPosition(int section) {int allPosition = 0;for (int i = 0; i < section; i++) {allPosition = allPosition + mListData.get(i).childlist.size();}allPosition = allPosition + section;return allPosition;}

效果图如下:

4、添加简单搜索,其实和滑动侧边SideBar的效果一样的,只是换一种方法,目前还未实现模糊搜索联系人的方法,其中的顶部搜索的输入框右边的删除图片借用了上一步中提到的博文里的思路,汉字拼音的转化也是如此。

目前最终效果图如下:

5、进一步优化:侧边栏字母的值跟随列表数据值变化而变化

Android获取通讯录联系人,右侧字母滑动索引相关推荐

  1. 微信联系人右侧字母滑动索引

    实现思路:通过自定义View在频幕右侧循环写入a~z;复写onTouchEvent @Overridepublic boolean onTouchEvent(MotionEvent event) {s ...

  2. Android 获取通讯录联系人,打开通讯录获取联系人信息;整个流程封装在基类中;

    打开原生通讯录获取联系人姓名和手机号 1.获取通讯录权限: <!--访问通讯录--><uses-permission android:name="android.permi ...

  3. 模拟微信联系人右侧字母滑动

    先看看效果图 具体代码如下(可以直接使用,不需要依赖其他东西) import android.annotation.TargetApi; import android.content.Context; ...

  4. android 仿微信联系人 首字母分组快速索引

    总结是一种习惯,不能停,一停人就懒了,都快一个月没有写了!该提提神了! 进入正题:android 仿微信联系人 首字母快速索引,先用下美团的索引效果图: 1.自定义View字母索引栏(右边那一列): ...

  5. Android软件开发之获取通讯录联系人信息

    点击打开链接http://blog.csdn.net/snwrking/article/details/7601794 Android软件开发之获取通讯录联系人信息 + android联系人信息的存储 ...

  6. 联系人列表字母排序索引(三)

    也是忙忙碌碌好几天,今天又有时间了,继续这个文章的编写. 阅读这篇文章之前,请先阅读 联系人列表字母排序索引(一) 联系人列表字母排序索引(二) 今天是这篇文章的最后一部分,主要内容包括以下几点: 1 ...

  7. Android获取通讯录信息

    Android获取通讯录信息 欢迎关注本人网站:rytter的私人博客网站 权限申请 自Android6.0以后,Android权限申请全部要求为动态申请(注:通讯录权限为危险权限),权限申请方法如下 ...

  8. Android获取手机联系人匹配用户表并按字母A Z排序展示

    1.前言 最近在做公司项目的时候遇到一个添加手机联系人的需求,主要有以下几个功能点: 读取联系人:读取用户手机上的通讯录里的联系人列表 好友排序:按照拼音顺序对好友进行排序,兼容英文数字符号等 字母索 ...

  9. Android获取手机联系人匹配用户表并按字母A-Z排序展示

    1.前言 最近在做公司项目的时候遇到一个添加手机联系人的需求,主要有以下几个功能点: 读取联系人:读取用户手机上的通讯录里的联系人列表 好友排序:按照拼音顺序对好友进行排序,兼容英文数字符号等 字母索 ...

最新文章

  1. 【Java报错】java.lang.ClassCastException: xxxClass cannot be cast to java.lang.Comparable 问题重现+解决
  2. html 和jsp 引入jquery_不用jsp怎么实现前后端交互?给萌新后端的ajax教程(1)
  3. Taro+react开发(2)--简介2
  4. python一次性输入3个数_python实现输入数字的连续加减方法
  5. 链表(Linked List)之单链表
  6. 系统机构设计师 - 软件质量属性
  7. uploadify没反应
  8. 相同MAC地址,相同IP的两天电脑为什么可以同时上网互不影响(转自Nothel的blog)
  9. mie散射理论方程_亚琛工业大学 计算化学方向 之OPT学习笔记第一部分第一节 静态光散射...
  10. 利用卷积神经网络(CNN)提取图片特征
  11. 李沐亚马逊资深首席科学家 - 动手学深度学习v2 -2安装
  12. 大麦盒子无线服务器连接超时,大麦盒子游戏联网失败怎么办
  13. angular 更新表单值的两种方法: setvalue,patchvalue
  14. java怎么实现复杂的考勤计算_考勤系统之计算工作小时数
  15. 其他——SPSS做线性回归分析最好的例子
  16. 详解Unity中的生命周期函数
  17. Android APP升级时解析程序包时出现问题
  18. 数据结构 笔记--向量 C++ 语言版 邓俊辉老师
  19. python 变量使用进阶
  20. 02 C语言使用队列实现缓存模块QueueBuffer

热门文章

  1. 推荐几款渗透测试常用的脚本(记得收藏)
  2. 松果出行 x StarRocks:实时数仓新范式的实践之路
  3. 『前端面试题纪实』2020/春+秋 实习
  4. centos7分区挂载大容量数据盘
  5. 论文笔记之Non-Local
  6. 阵列信号DOA估计系列(三).MVDR/Capon波束形成(附代码)
  7. Pytorch学习之torch----Reduction Ops
  8. Fragment的Tag
  9. 运行SVO报错fatal error: sophus/se3.hpp: No such file or directory
  10. 0.爬虫介绍及requests库的使用