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


    具体实现过程如下:

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

    1     

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

     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 {
    17     private int resource;// 需要渲染的item布局文件
    18     private SectionIndexer mIndexer;// 字母表分组工具
    19 
    20     public ContactAdapter(Context context, int textViewResourceId,List 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 contacts = new ArrayList();// 存储所有手机中的联系人
     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 
     2 
     3 
     4     
     9 
    10     
    14 
    15     
    16 
    17 

    布局文件:

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

     1 
     6 
     7     
    16     
    17 
    18     
    24 
    25         
    33     
    34 
    35     

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

     1 
     5 
     6     
    11 
    12         
    21     
    22 
    23     
    27 
    28         
    35 
    36         
    41 
    42             
    50 
    51             
    60         
    61     
    62 
    63 
  • 相关阅读:
    4_使用预训练模型 微调训练CIFAR10
    2022年下半年软考信息安全工程师如何备考?
    高性能本地缓存Ristretto(一)——存储策略
    2023年tiktok自动化运营软件新排名看这里!
    10、集合类不安全(list不安全解决(CopyOnWriteArrayList))
    springboot/ssm宠物领养救助平台Java流浪动物救助管理系统web
    网页制作基础大二dw作业HTML+CSS+JavaScript云南我的家乡旅游景点
    JDBC(Java Database Connectivity)
    matlab-实现-BP-神经网络
    【LeetCode热题100】--153.寻找旋转排序数组中的最小值
  • 原文地址:https://blog.csdn.net/m0_62089210/article/details/126399822