需求
通过搜索联系人的姓名获取相应的详细人信息,也可通过右侧字母条搜索相应的联系人信息。
主要代码如下:
MainActivity

public class MainActivity extends AppCompatActivity {private ListView sortListView;private SideLetterUtil sideLetterUtil;private TextView dialog;private SortAdapter adapter;private ClearEditText mClearEditText;private String mobile,//被授权人电话号码name;//被授权人姓名/*** 查询通讯录名字*/private Uri contactsUrl = ContactsContract.Contacts.CONTENT_URI;private ContentResolver resolver;private List<ContactsBean> nameList;/*** 汉字转换成拼音的类*/private CharacterParser characterParser;private List<ContactsBean> SourceDateList;/*** 根据拼音来排列ListView里面的数据类*/private ContactsPinyinComparator pinyinComparator;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);getPersimmionInfo();}private void getPersimmionInfo() {if (Build.VERSION.SDK_INT >= 23) {//1. 检测是否添加权限   PERMISSION_GRANTED  表示已经授权并可以使用if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {//手机为Android6.0的版本,权限未授权去i请授权//2. 申请请求授权权限//1. Activity// 2. 申请的权限名称// 3. 申请权限的 请求码ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CONTACTS//通话录}, 1005);} else {//手机为Android6.0的版本,权限已授权可以使用// 执行下一步initContacts();}} else {//手机为Android6.0以前的版本,可以使用initContacts();}}//  重写方法    当权限申请后     执行 接收结果的作用@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);// 先判断请求码 与 请求时的  是否一致if (requestCode == 1005) {//  判断请求结果长度     且  结果 为  允许访问  则 进行使用;第一次授权成功后if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {// 可以使用initContacts();} else {//未授权不可以使用// 摄像机或读写内存卡权限授权将不能使用以下功能。Toast.makeText(MainActivity.this, "未授权不可以使用", Toast.LENGTH_SHORT).show();}}}private void initContacts() {//实例化汉字转拼音类characterParser = CharacterParser.getInstance();pinyinComparator = new ContactsPinyinComparator();//右侧26个字母和#sideLetterUtil = (SideLetterUtil) findViewById(R.id.sidrbar);//中间显示字母dialog = (TextView) findViewById(R.id.dialog);sideLetterUtil.setTextView(dialog);//设置右侧触摸监听sideLetterUtil.setOnTouchingLetterChangedListener(new SideLetterUtil.OnTouchingLetterChangedListener() {@Overridepublic void onTouchingLetterChanged(String s) {//该字母首次出现的位置int position = adapter.getPositionForSection(s.charAt(0));if (position != -1) {sortListView.setSelection(position);}}});sortListView = (ListView) findViewById(R.id.lv_contacts_item);/*** 查询通讯录名字*/nameList = new ArrayList<>();resolver = getContentResolver();//用于查询电话号码的URIUri phoneUri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;// 查询的字段String[] projection = {ContactsContract.CommonDataKinds.Phone._ID,//IdContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,//通讯录姓名ContactsContract.CommonDataKinds.Phone.DATA1, "sort_key",//通讯录手机号ContactsContract.CommonDataKinds.Phone.CONTACT_ID,//通讯录IdContactsContract.CommonDataKinds.Phone.PHOTO_ID,//手机号IdContactsContract.CommonDataKinds.Phone.LOOKUP_KEY};Cursor cursor = resolver.query(phoneUri, projection, null, null, null);while ((cursor.moveToNext())) {String name = cursor.getString(1);String phone = cursor.getString(2);nameList.add(new ContactsBean(name, phone));}SourceDateList = filledData(nameList);// 根据a-z进行排序源数据Collections.sort(SourceDateList, pinyinComparator);adapter = new SortAdapter(this, SourceDateList);sortListView.setAdapter(adapter);adapter.setOnCliker(new SortAdapter.OnClicker() {@Overridepublic void onClik(String name1, String phone1) {//这里要利用adapter.getItem(position)来获取当前position所对应的对象mobile = phone1;if (MobileUtil.isMobileNO(mobile)) {//无通讯姓名则为StrConfig.CONTACTS_NAME_NULLname = (TextUtils.equals(name1, "未备注联系人"))? "null" : name1;Toast.makeText(MainActivity.this,name + mobile, Toast.LENGTH_SHORT).show();} else {//该用户无手机号,或手机号格式不正确Toast.makeText(MainActivity.this,"该用户无手机号,或手机号格式不正确", Toast.LENGTH_SHORT).show();}}});mClearEditText = findViewById(R.id.filter_edit);//根据输入框输入值的改变来过滤搜索mClearEditText.addTextChangedListener(new TextWatcher() {@Overridepublic void onTextChanged(CharSequence s, int start, int before, int count) {//当输入框里面的值为空,更新为原来的列表,否则为过滤数据列表filterData(s.toString());}@Overridepublic void beforeTextChanged(CharSequence s, int start, int count,int after) {}@Overridepublic void afterTextChanged(Editable s) {}});}/*** 为ListView填充数据*/private List<ContactsBean> filledData(List<ContactsBean> date) {List<ContactsBean> mSortList = new ArrayList<ContactsBean>();for (int i = 0; i < date.size(); i++) {ContactsBean contactsBean = new ContactsBean();contactsBean.setName(date.get(i).getName());contactsBean.setPhone(date.get(i).getPhone());//汉字转换成拼音String pinyin = characterParser.getSelling(date.get(i).getName());String sortString = pinyin.substring(0, 1).toUpperCase();// 正则表达式,判断首字母是否是英文字母if (sortString.matches("[A-Z]")) {contactsBean.setSortLetters(sortString.toUpperCase());} else {contactsBean.setSortLetters("#");}mSortList.add(contactsBean);}return mSortList;}/*** 根据输入框中的值来过滤数据并更新ListView** @param filterStr*/private void filterData(String filterStr) {List<ContactsBean> filterDateList = new ArrayList<ContactsBean>();if (TextUtils.isEmpty(filterStr)) {filterDateList = SourceDateList;} else {filterDateList.clear();for (ContactsBean contactsBean : SourceDateList) {String name = contactsBean.getName();if (name.indexOf(filterStr.toString()) != -1 || characterParser.getSelling(name).startsWith(filterStr.toString())) {filterDateList.add(contactsBean);}}}// 根据a-z进行排序Collections.sort(filterDateList, pinyinComparator);adapter.updateListView(filterDateList);}
}

SortAdapter

public class SortAdapter extends BaseAdapter implements SectionIndexer {private List<ContactsBean> list = null;private Context mContext;private OnClicker onClicker;public SortAdapter(Context mContext, List<ContactsBean> list) {this.mContext = mContext;this.list = list;}/*** 当ListView数据发生变化时,调用此方法来更新ListView** @param list*/public void updateListView(List<ContactsBean> list) {this.list = list;notifyDataSetChanged();}public int getCount() {return this.list.size();}public Object getItem(int position) {return list.get(position);}public long getItemId(int position) {return position;}public View getView(final int position, View view, ViewGroup arg2) {ViewHolder viewHolder = null;final ContactsBean mContent = list.get(position);if (view == null) {viewHolder = new ViewHolder();view = LayoutInflater.from(mContext).inflate(R.layout.contacts_item, null);viewHolder.rlContacts = view.findViewById(R.id.rl_contacts);viewHolder.tvTitle = view.findViewById(R.id.tv_contacts_item_title);viewHolder.tvLetter = view.findViewById(R.id.tv_contacts_item_catalog);view.setTag(viewHolder);} else {viewHolder = (ViewHolder) view.getTag();}//根据position获取分类的首字母的Char ascii值int section = getSectionForPosition(position);//如果当前位置等于该分类首字母的Char的位置 ,则认为是第一次出现if (position == getPositionForSection(section)) {viewHolder.tvLetter.setVisibility(View.VISIBLE);viewHolder.tvLetter.setText(mContent.getSortLetters());} else {viewHolder.tvLetter.setVisibility(View.GONE);}final String mobile = this.list.get(position).getPhone().replaceAll(" ", "").replaceAll("\\+", "").replaceAll("-", "");viewHolder.tvTitle.setText(this.list.get(position).getName());viewHolder.rlContacts.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {onClicker.onClik(list.get(position).getName(), mobile);}});return view;}final static class ViewHolder {private TextView tvLetter,//首字母tvTitle;//名字private RelativeLayout rlContacts;//tvIsImpower;//是否授权}/*** 根据ListView的当前位置获取分类的首字母的Char ascii值*/public int getSectionForPosition(int position) {return list.get(position).getSortLetters().charAt(0);}/*** 根据分类的首字母的Char ascii值获取其第一次出现该首字母的位置*/public int getPositionForSection(int section) {for (int i = 0; i < getCount(); i++) {String sortStr = list.get(i).getSortLetters();char firstChar = sortStr.toUpperCase().charAt(0);if (firstChar == section) {return i;}}return -1;}public void setOnCliker(OnClicker onClicker) {this.onClicker = onClicker;}/*** 提取英文的首字母,非英文字母用#代替。** @param str* @return*/private String getAlpha(String str) {String sortStr = str.trim().substring(0, 1).toUpperCase();// 正则表达式,判断首字母是否是英文字母if (sortStr.matches("[A-Z]")) {return sortStr;} else {return "#";}}@Overridepublic Object[] getSections() {return null;}public interface OnClicker {void onClik(String name, String phone);}
}

SideLetterUtil

public class SideLetterUtil extends View {// 触摸事件private OnTouchingLetterChangedListener onTouchingLetterChangedListener;public static String[] b = {"常用", "A", "B", "C", "D", "E", "F", "G", "H", "I","J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V","W", "X", "Y", "Z", "#"};private int choose = -1;// 选中private Paint paint = new Paint();private TextView mTextDialog;private Context context;public void setTextView(TextView mTextDialog) {this.mTextDialog = mTextDialog;// this.mTextDialog.setTextColor(getResources().getColor(R.color.primary_green));}public SideLetterUtil(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);this.context = context;}public SideLetterUtil(Context context, AttributeSet attrs) {super(context, attrs);this.context = context;}public SideLetterUtil(Context context) {super(context);this.context = context;}/*** 重写这个方法*/protected void onDraw(Canvas canvas) {super.onDraw(canvas);// 获取焦点改变背景颜色.int height = getHeight();// 获取对应高度int width = getWidth(); // 获取对应宽度int singleHeight = height / b.length;// 获取每一个字母的高度for (int i = 0; i < b.length; i++) {paint.setColor(Color.rgb(33, 65, 98));paint.setColor(getResources().getColor(R.color.primary_green));paint.setTypeface(Typeface.DEFAULT_BOLD);paint.setAntiAlias(true);paint.setTextSize(DensityUtil.dp2px(context, 8));// 选中的状态if (i == choose) {paint.setColor(Color.parseColor("#3399ff"));paint.setFakeBoldText(true);}// x坐标等于中间-字符串宽度的一半.float xPos = width / 2 - paint.measureText(b[i]) / 2;float yPos = singleHeight * i + singleHeight;canvas.drawText(b[i], xPos, yPos, paint);paint.reset();// 重置画笔}}@Overridepublic boolean dispatchTouchEvent(MotionEvent event) {final int action = event.getAction();final float y = event.getY();// 点击y坐标final int oldChoose = choose;final OnTouchingLetterChangedListener listener = onTouchingLetterChangedListener;final int c = (int) (y / getHeight() * b.length);// 点击y坐标所占总高度的比例*b数组的长度就等于点击b中的个数.switch (action) {case MotionEvent.ACTION_UP:setBackgroundDrawable(new ColorDrawable(0x00000000));choose = -1;//invalidate();if (mTextDialog != null) {mTextDialog.setVisibility(View.INVISIBLE);}break;default:setBackgroundResource(R.drawable.sidebar_background);if (oldChoose != c) {if (c >= 0 && c < b.length) {if (listener != null) {listener.onTouchingLetterChanged(b[c]);}if (mTextDialog != null) {mTextDialog.setText(b[c]);mTextDialog.setVisibility(View.VISIBLE);}choose = c;invalidate();}}break;}return true;}/*** 向外公开的方法** @param onTouchingLetterChangedListener*/public void setOnTouchingLetterChangedListener(OnTouchingLetterChangedListener onTouchingLetterChangedListener) {this.onTouchingLetterChangedListener = onTouchingLetterChangedListener;}/*** 接口*/public interface OnTouchingLetterChangedListener {public void onTouchingLetterChanged(String s);}}

效果图

  • 源码: Android开发读取通讯录信息

Android开发读取通讯录信息相关推荐

  1. ios通过app读取通讯录信息

    iOS通过app读取通讯录信息,读取通讯录信息时需要加载AddressBookUI 和AddressBook两个包,并且引入头文件 #import <AddressBook/AddressBoo ...

  2. Android开发 读取手机通讯录

    目录 一.通讯录界面布局 activity_contact.xml 界面布局: contact_item.xml 条目界面布局: item_bg.xml 条目界面的背景文件(drawable文件夹中创 ...

  3. android通讯录上传服务器,Android 实现读取通讯录并上传服务器

    关键技术 - 内容解析者Resolver - ListView - Socket网络编程 权限申请 //需要在Manifest.xml文件中申请权限 布局: xmlns:app="http: ...

  4. Android开发手机通讯录

    Android Studio开发手机通讯录 课程设计 课程设计要求 课程设计题目 题目1 通讯录管理 题目2 拨号和短信管理 代码实现 首先我们先来理清楚思路 创建数据库 设置适配器 主页面 添加联系 ...

  5. java 获取 邮箱联系人_在android中读取联系人信息的程序,包括读取联系人姓名、手机号码和邮箱...

    /** 读取联系人的信息*/ public voidtestReadAllContacts() { Cursor cursor= this.getContext().getContentResolve ...

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

    首先先看一下效果图再说吧: 具体实现过程如下: 先在AndroidManifest.xml文件中添加读取联系人的权限: 1 <uses-permission android:name=" ...

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

    具体实现过程如下: 先在AndroidManifest.xml文件中添加读取联系人的权限: 1 <uses-permission android:name="android.permi ...

  8. Revit开发读取CAD信息

    在Revit里链接的CAD通过API 能获取到到图层信息和图层里的几何信息 文字信息目前应该是还获取不到的 几何信息可以直接通过Geometry来获取 图形信息可以通过GeometryObject的G ...

  9. 身份证读取设备开发解决方案:2、Android下通过usb转串口读取身份证信息

    身份证读取设备开发解决方案:2.Android下通过usb转串口读取身份证信息 文章目录 身份证读取设备开发解决方案:2.Android下通过usb转串口读取身份证信息 1. 前言 2. 准备 3. ...

最新文章

  1. 宝塔linux计划任务ftp,宝塔面板定时备份网站及数据库至FTP存储空间图文教程
  2. // synopsys_translate_off,parallel_case 和 full_case
  3. JS实现App扫码网页端登录
  4. CSP前训练错误集锦
  5. Ubuntu linux上Nautilus安装RabbitVCS扩展
  6. 论文浅尝 - AAAI2020 | 基于知识图谱进行对话目标规划的开放域对话生成技术
  7. 我看了全部文件的字符串资源
  8. Matlab中的画图函数
  9. hackerrank Java Data Structures
  10. 重装系统后如何恢复mysql服务
  11. 镜像在国外仓库,拉取不了怎么办
  12. 基于jQuery的鼠标右键菜单
  13. maven打包报错 Failed to execute goal org.apache.maven.plugins:maven-jar-plugin:3.0.2:jar
  14. 2021年软件类第十二届蓝桥杯 省赛 python组 F-J题解
  15. 免费PPT模板 | 《超能陆战队》暖心大白通用演示PPT模板
  16. BIOS IDE 改 AHCI
  17. ARM汇编----GBLA,GBLL及GBLS
  18. 2022年山东省职业院校技能大赛高职组“网络系统管理”赛项规程
  19. 奥维查看行政边界_百度地图获取行政范围边界
  20. ubuntu设置root密码,强制删除用户及用户文件。

热门文章

  1. 剑走偏锋之ICMP隧道
  2. oracle 查看考试成绩,oracle认证考试成绩如何查询?
  3. window下使用C++ Bonjour配置服务
  4. L2-025 分而治之
  5. C++学习 11.18.19
  6. windows下pip无法升级
  7. python自动化办公读后感_《Python编程快速上手——让繁琐的工作自动化》读书笔记3...
  8. php快速计算子网掩码的前缀长度
  9. 如何查看网站服务器的地址
  10. 中国电信中兴F412光猫——IPTV与网络单线复用