Android 用Java实现通讯录根据中文拼音排序功能
此内容包含在我的另外一篇博客,学习开源项目MyDiary第二天中。这是MyDiary的网址,https://github.com/DaxiaK/MyDiary,本篇主要介绍这个功能的具体代码。
加入现在有一个通讯录功能需实现,已经完成了塞入数据库数据,并在RecyclerView中显示它们。但是,如果并不按照拼音进行额外的排序,通讯录的数据库只能正序或倒序显示,显然是不方便的。如果按照拼音进行排序,并显示它们的头部(如测试号码显示头部T),就像这样。汉字转换为拼音可以使用PinYin4j.jar,这个包,十分强大。下载好这个包应该怎么使用呢,当时参考了这篇博客,(放入lib文件夹后直接右键包并找到add to ... 就可以了)https://blog.csdn.net/ygd1994/article/details/51346984。
已经存入数据库的数据是不能排序的,如果需要将它们排序,MyDiary中是将数据库中通讯录的数据放入到一个List中,然后List进行排序,排序后得到的数据就是按照首汉字拼音的,像下图(左右两图没有联系,当时是分开截图的)。现在由于是使用LiveData和Room来操作数据库,这点和MyDiary不同,因此要取LiveData这个List的数据再一个个add加到ContacsNamesEntity这个List中。ContacsNamesEntity是用private List<ContactsEntity> ContacsNamesEntity新建的类,ContactsEntity这个类包含了通讯录中的信息,几乎和数据库中的列是相同的。
ContacsNamesEntity.java
1 package com.example.ourdiary.contacts; 2 3 /** 4 *将long的contacts_ Id改成了int的 5 *@author home 6 *@time 2021/5/28 19:12 7 */ 8 public class ContactsEntity { 9 10 private int contactsId; 11 private String name; 12 private String phoneNumber; 13 private String photo; 14 private String sortLetters; 15 16 public ContactsEntity(int contactsId, String name, String phoneNumber, String photo) { 17 this.contactsId = contactsId; 18 this.name = name; 19 this.phoneNumber = phoneNumber; 20 this.photo = photo; 21 } 22 23 public int getContactsId() { 24 return contactsId; 25 } 26 27 public String getName() { 28 return name; 29 } 30 31 public String getPhoneNumber() { 32 return phoneNumber; 33 } 34 35 public String getPhoto() { 36 return photo; 37 } 38 39 public String getSortLetters() { 40 return sortLetters; 41 } 42 43 public void setSortLetters(String sortLetters) { 44 this.sortLetters = sortLetters; 45 } 46 }
loadContacts类是在ContactsActivity.java中的,它将会放入onCreate中使用。这里getSpecificContacts为什么是设置1呢?因为现在主页面的RecyclerView中没有完成(最终的成果是根据不同的通讯录显示不同的通讯录内容,就像学校通许录里面专门放同学老师的电话,而足球散兵通讯录专门放踢球小伙伴的电话,而区分它们的是一个id,显示它们时就用条件查询where id = 什么什么,现在没有弄好,但是表建好了,便用1了)。设置一个观察者专门观察LivaData是否变化,然后将它们一个一个添加到List中。得以与Room,数据是可以自动检查到变化,每一次变化时便情况列表,重新增加。
1 private void loadContacts() { 2 3 mContactViewModel.getSpecificContacts(1).observe(this, new Observer<List<Contact>>() { 4 @Override 5 public void onChanged(List<Contact> contacts) { 6 7 contactsNamesList.clear(); 8 9 for (int i = 0; i < contacts.size(); i++) { 10 contactsNamesList.add(new ContactsEntity( 11 contacts.get(i).getId(), 12 contacts.get(i).getContacts_name(), 13 contacts.get(i).getContacts_phone_number(), 14 contacts.get(i).getStrId()));//photo先塞入数据库数据 后期是要放图片的 15 } 16 17 sortContacts(); 18 19 } 20 });
sortContacts、sortContactsCN这两个类同样是在ContactsActivity.java这个大类中。
1 /**对列表进行排序*/ 2 private void sortContacts() { 3 for (ContactsEntity contactsEntity : contactsNamesList) { 4 String sortString = contactsEntity.getName().substring(0, 1).toUpperCase(); 5 sortContactsCN(contactsEntity, sortString); 6 } 7 Collections.sort(contactsNamesList, new LetterComparator()); 8 } 9 10 /**根据中文进行排序*/ 11 private String sortContactsCN(ContactsEntity contactsEntity, String sortString) { 12 if (sortString.matches("[\\u4E00-\\u9FA5]")) { 13 String[] arr = PinyinHelper.toHanyuPinyinStringArray(sortString.trim().charAt(0)); 14 sortString = arr[0].substring(0, 1).toUpperCase(); 15 } 16 if (sortString.matches("[A-Z]")) { 17 contactsEntity.setSortLetters(sortString.toUpperCase()); 18 } else { 19 contactsEntity.setSortLetters("#"); 20 } 21 return sortString; 22 }
随后在对应RecyclerViewAdapter中显示它们,
1 /**需要载入所有通讯录再进行排序 不然弄不了*/ 2 @Override 3 public void onBindViewHolder(@NonNull ContactsAdapter.TopicViewHolder holder, int position) { 4 // Contact contact = getItem(position); 5 6 if (showHeader(position)) { 7 holder.getHeader().setVisibility(View.VISIBLE); 8 holder.getHeader().setText(contactsNamesList.get(position).getSortLetters()); 9 } else { 10 holder.getHeader().setVisibility(View.GONE); 11 } 12 holder.getTVName().setText(contactsNamesList.get(position).getName()); 13 holder.getTVPhoneNumber().setText(contactsNamesList.get(position).getPhoneNumber()); 14 holder.setItemPosition(position); 15 } 16 17 /** 18 *让每个通讯录显示它的头部,例如Contacts_Name 为test,那么就显示它的头部T 19 * 判断的方法是检查每个Contact的getContacts_name首字母是否相同 20 *@author home 21 *@time 2021/5/26 11:37 22 */ 23 private boolean showHeader(final int position) { 24 if (position == 0) { 25 return true; 26 } else { //如果不是位于rv的0号位置,那么是可以去得到position-1的,不会为空 27 if (!contactsNamesList.get(position - 1).getSortLetters().equals( 28 contactsNamesList.get(position).getSortLetters())) { 29 return true; 30 } else { 31 return false; 32 } 33 } 34 }
全部代码可以倒github上查看,https://github.com/BILY5354/OurDiaryGit。