Android Address Book fuzzy search (numbers, names, initials, full spelling), batch select contacts
Android Address Book fuzzy search (numbers, names, initials, full spelling), batch select contacts
The company encountered a requirement in a recent project that needed to read contacts in the address book and support fuzzy queries and batch selection of contacts. Several examples were found online, fuzzy query is a little flawed. Finally, I optimized the fuzzy query of contacts based on the hard work of all netizens. the following functions are supported:
1. Search by number, name, and initial letter in a fuzzy match
2. Support for [A-Z] Quick navigation
3. Supports the first letter of contact.
4. Batch selection of contacts is supported.
Code structure:
Main Code:
ContactsActivity:
Package com. xbc. utils. activity; import java. util. arrayList; import java. util. collections; import java. util. list; import java. util. locale; import android. app. activity; import android. content. contentResolver; import android. database. cursor; import android. OS. bundle; import android. provider. contactsContract. commonDataKinds. phone; import android. text. editable; import android. text. textUtils; import android. text. textWatcher; import android. util. log; import android. view. view; import android. view. view. onClickListener; import android. widget. adapterView; import android. widget. adapterView. onItemClickListener; import android. widget. editText; import android. widget. imageView; import android. widget. listView; import android. widget. textView; import android. widget. toast; import com. xbc. contacts. r; import com. xbc. utils. activity. contactsSortAdapter. viewHolder; import com. xbc. utils. activity. sideBar. onTouchingLetterChangedListener; public class ContactsActivity extends Activity {ListView mListView; EditText etSearch; ImageView ivClearText; private SideBar sideBar; private TextView dialog; private List
MAllContactsList; private ContactsSortAdapter adapter;/*** convert Chinese characters into Pinyin classes */private CharacterParser characterParser;/*** sort data classes in ListView by pinyin */private PinyinComparator pinyinComparator; @ Overrideprotected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. layout_contacts); init ();} private void init () {initView (); initListener (); loadContacts ();} private void initListener () {/** clear input characters **/ivClearText. setOnClickListener (new OnClickListener () {@ Overridepublic void onClick (View v) {etSearch. setText () ;}}); etSearch. new TextWatcher () {@ Overridepublic void onTextChanged (CharSequence arg0, int arg1, int arg2, int arg3) {}@ Overridepublic void beforeTextChanged (CharSequence arg0, int arg1, int arg2, int arg3) {}@ Overridepublic void afterTextChanged (Editable e) {String content = etSearch. getText (). toString (); if (. equals (content) {ivClearText. setVisibility (View. INVISIBLE);} else {ivClearText. setVisibility (View. VISIBLE);} if (content. length ()> 0) {ArrayList
FileterList = (ArrayList
) Search (content); adapter. updateListView (fileterList); // mAdapter. updateData (mContacts);} else {adapter. updateListView (mAllContactsList);} mListView. setSelection (0) ;}}); // set the right side of the [A-Z] Quick navigation bar to touch the listening sideBar. setOnTouchingLetterChangedListener (new OnTouchingLetterChangedListener () {@ Overridepublic void onTouchingLetterChanged (String s) {// the first occurrence position of the letter int position = adapter. getPositionForSection (s. charAt (0); if (po Sition! =-1) {mListView. setSelection (position) ;}}); mListView. setOnItemClickListener (new OnItemClickListener () {@ Overridepublic void onItemClick (AdapterView
AdapterView, View view, int position, long arg3) {ViewHolder viewHolder = (ViewHolder) view. getTag (); viewHolder. cbChecked. optional mclick (); adapter. toggleChecked (position) ;}}) ;}private void initView () {sideBar = (SideBar) findViewById (R. id. sidrbar); dialog = (TextView) findViewById (R. id. dialog); sideBar. setTextView (dialog); ivClearText = (ImageView) findViewById (R. id. ivClearText); etSearch = (EditText) findViewById (R. id. et_search); mListView = (ListView) findViewById (R. id. lv_contacts);/** set adapter for ListView **/characterParser = CharacterParser. getInstance (); mAllContactsList = new ArrayList
(); PinyinComparator = new PinyinComparator (); Collections. sort (mAllContactsList, pinyinComparator); // sort source data by a-z adapter = new ContactsSortAdapter (this, mAllContactsList); mListView. setAdapter (adapter);} private void loadContacts () {new Thread (new Runnable () {@ Overridepublic void run () {try {ContentResolver resolver = getApplicationContext (). getContentResolver (); Cursor phoneCursor = resolver. query (Phone. CONTENT_URI, new String [] {Phone. DISPLAY_NAME, Phone. NUMBER, sort_key}, null, null, sort_key collate localized asc); if (phoneCursor = null | phoneCursor. getCount () = 0) {Toast. makeText (getApplicationContext (), does not get the permission to read the contact or does not get the contact data, Toast. LENGTH_SHORT ). show (); return;} int PHONES_NUMBER_INDEX = phoneCursor. getColumnIndex (Phone. NUMBER); int PHONES_DISPLAY_NAME_INDEX = phoneCursor. getColumnIndex (Phone. DISPLAY_NAME); int SORT_KEY_INDEX = phoneCursor. getColumnIndex (sort_key); if (phoneCursor. getCount ()> 0) {mAllContactsList = new ArrayList
(); While (phoneCursor. moveToNext () {String phoneNumber = phoneCursor. getString (PHONES_NUMBER_INDEX); if (TextUtils. isEmpty (phoneNumber) continue; String contactName = phoneCursor. getString (PHONES_DISPLAY_NAME_INDEX); String sortKey = phoneCursor. getString (SORT_KEY_INDEX); // System. out. println (sortKey); SortModel sortModel = new SortModel (contactName, phoneNumber, sortKey); // The system sortkey is preferentially used, and the String sortLetters = sortKey is not obtained ); if (sortLetters = null) {sortLetters = getSortLetter (contactName);} sortModel. sortLetters = sortLetters; sortModel. sortToken = parseSortKey (sortKey); mAllContactsList. add (sortModel) ;}} phoneCursor. close (); runOnUiThread (new Runnable () {public void run () {Collections. sort (mAllContactsList, pinyinComparator); adapter. updateListView (mAllContactsList) ;}});} catch (Exception e) {Log. e (xbc, e. getLocalizedMessage ());}}}). start ();}/*** name to pinyin, with the first letter * @ param name * @ return */private String getSortLetter (String name) {String letter = #; if (name = null) {return letter;} // convert Chinese characters to pinyin String pinyin = characterParser. getSelling (name); String sortString = pinyin. substring (0, 1 ). toUpperCase (Locale. CHINESE); // regular expression to determine whether the first letter is an English letter, if (sortString. matches ([A-Z]) {letter = sortString. toUpperCase (Locale. CHINESE);} return letter;}/*** get the first letter of sort_key * @ param sortKey * @ return */private String getSortLetterBySortKey (String sortKey) {if (sortKey = null |. equals (sortKey. trim () {return null;} String letter =#; // convert Chinese characters to PinYin String sortString = sortKey. trim (). substring (0, 1 ). toUpperCase (Locale. CHINESE); // regular expression to determine whether the first letter is an English letter, if (sortString. matches ([A-Z]) {letter = sortString. toUpperCase (Locale. CHINESE);} return letter;}/*** fuzzy query * @ param str * @ return */private List
Search (String str) {List
FilterList = new ArrayList
(); // The filtered listif (str. matches (^ ([0-9] | [/+]) * $) {// Regular Expression matching number for (SortModel contact: mAllContactsList) {if (contact. number! = Null & contact. name! = Null) {if (contact. number. contains (str) | contact. name. contains (str) {if (! FilterList. contains (contact) {filterList. add (contact) ;}}} else {for (SortModel contact: mAllContactsList) {if (contact. number! = Null & contact. name! = Null) {// name full match, name combination, name full match if (contact. name. toLowerCase (Locale. CHINESE ). contains (str. toLowerCase (Locale. CHINESE) | contact. sortKey. toLowerCase (Locale. CHINESE ). replace (,). contains (str. toLowerCase (Locale. CHINESE) | contact. sortToken. simpleSpell. toLowerCase (Locale. CHINESE ). contains (str. toLowerCase (Locale. CHINESE) | contact. sortToken. wholeSpell. toLowerCase (Locale. CHINESE ). contains (str. toLow ErCase (Locale. CHINESE) {if (! FilterList. contains (contact) {filterList. add (contact) ;}}}return filterList;} String chReg = [\ u4E00-\ u9FA5] +; // match Chinese strings // String chReg = [^ \ u4E00-\ u9FA5]; // match characters other than Chinese characters/*** parse sort_key, encapsulate the short spelling, full spell * @ param sortKey * @ return */public SortToken parseSortKey (String sortKey) {SortToken token = new SortToken (); if (sortKey! = Null & sortKey. length ()> 0) {// The Chinese character String [] enStrs = sortKey. replace (,). split (chReg); for (int I = 0, length = enStrs. length; I <length; I ++) {if (enStrs [I]. length ()> 0) {// concatenate a simple token. simpleSpell + = enStrs [I]. charAt (0); token. wholeSpell + = enStrs [I] ;}} return token ;}}