天天看點

Android之實作系統聯系人軟體的分組和字母提示效果

聯系人分章節顯示以及ListView快速滑動顯示聯系人首字母例子,查閱網上很多這樣的例子後,發現普遍是從系統源碼裡面抽取的,而且普遍比較複雜,這裡做了精簡,擴充性較強,移植起來非常友善。

1.FastContactSearchDemoActivity.java

[javascript] view plain copy print ?

  1. package com.zhf.FastContactSearchDemo; 
  2. import java.util.ArrayList; 
  3. import java.util.Collections; 
  4. import java.util.HashMap; 
  5. import java.util.List; 
  6. import java.util.Set; 
  7. import java.util.regex.Pattern; 
  8. import android.app.Activity; 
  9. import android.content.AsyncQueryHandler; 
  10. import android.content.ContentResolver; 
  11. import android.content.ContentValues; 
  12. import android.content.Context; 
  13. import android.database.Cursor; 
  14. import android.net.Uri; 
  15. import android.os.Bundle; 
  16. import android.view.LayoutInflater; 
  17. import android.view.View; 
  18. import android.view.ViewGroup; 
  19. import android.widget.BaseAdapter; 
  20. import android.widget.ListView; 
  21. import android.widget.SectionIndexer; 
  22. import android.widget.TextView; 
  23. public class FastContactSearchDemoActivityextends Activity { 
  24.     private BaseAdapter adapter; 
  25.     private ListView personList; 
  26.     private AsyncQueryHandler asyncQuery; 
  27.     private staticfinal String NAME ="name", NUMBER ="number", 
  28.             SORT_KEY = "sort_key"; 
  29.     @Override 
  30.     public void onCreate(Bundle savedInstanceState) { 
  31.         super.onCreate(savedInstanceState); 
  32.         setContentView(R.layout.main); 
  33.         personList = (ListView) findViewById(R.id.listView); 
  34.         asyncQuery = new MyAsyncQueryHandler(getContentResolver()); 
  35.     } 
  36.     @Override 
  37.     protected void onResume() { 
  38.         super.onResume(); 
  39.         Uri uri = Uri.parse("content://com.android.contacts/data/phones"); // 聯系人的Uri 
  40.         String[] projection = { "_id","display_name","data1","sort_key" };// 查詢的列 
  41.         asyncQuery.startQuery(0, null, uri, projection,null,null, 
  42.                 "sort_key COLLATE LOCALIZED asc");// 按照sort_key升序查詢 
  43.     } 
  44.     private class MyAsyncQueryHandlerextends AsyncQueryHandler { 
  45.         public MyAsyncQueryHandler(ContentResolver cr) { 
  46.             super(cr); 
  47.         } 
  48.         @Override 
  49.         protected void onQueryComplete(int token, Object cookie, Cursor cursor) { 
  50.             if (cursor != null && cursor.getCount() > 0) { 
  51.                 List<ContentValues> list = new ArrayList<ContentValues>(); 
  52.                 cursor.moveToFirst(); 
  53.                 for (int i = 0; i < cursor.getCount(); i++) { 
  54.                     ContentValues cv = new ContentValues(); 
  55.                     cursor.moveToPosition(i); 
  56.                     String name = cursor.getString(1); 
  57.                     String number = cursor.getString(2); 
  58.                     String sortKey = cursor.getString(3); 
  59.                     if (number.startsWith("+86")) {// 去除多餘的中國地區号碼标志,對這個程式沒有影響。 
  60.                         cv.put(NAME, name); 
  61.                         cv.put(NUMBER, number.substring(3)); 
  62.                         cv.put(SORT_KEY, sortKey); 
  63.                     } else { 
  64.                         cv.put(NAME, name); 
  65.                         cv.put(NUMBER, number); 
  66.                         cv.put(SORT_KEY, sortKey); 
  67.                     } 
  68.                     list.add(cv); 
  69.                 } 
  70.                 if (list.size() > 0) { 
  71.                     setAdapter(list); 
  72.                 } 
  73.             } 
  74.         } 
  75.     } 
  76.     private void setAdapter(List<ContentValues> list) { 
  77.         adapter = new ListAdapter(this, list); 
  78.         personList.setAdapter(adapter); 
  79.     } 
  80.     private staticclass ViewHolder { 
  81.         TextView alpha; 
  82.         TextView name; 
  83.         TextView number; 
  84.     } 
  85.     private class ListAdapterextends BaseAdapterimplements SectionIndexer { 
  86.         private LayoutInflater inflater; 
  87.         private List<ContentValues> list; 
  88.         private HashMap<String, Integer> alphaIndexer;//儲存每個索引在list中的位置【#-0,A-4,B-10】 
  89.         private String[] sections;//每個分組的索引表【A,B,C,F...】 
  90.         public ListAdapter(Context context, List<ContentValues> list) { 
  91.             this.inflater = LayoutInflater.from(context); 
  92.             this.list = list; // 該list是已經排序過的集合,有些項目中的資料必須要自己進行排序。 
  93.             this.alphaIndexer =new HashMap<String, Integer>(); 
  94.             for (int i =0; i <list.size(); i++) { 
  95.                 String name = getAlpha(list.get(i).getAsString(SORT_KEY)); 
  96.                 if(!alphaIndexer.containsKey(name)){//隻記錄在list中首次出現的位置 
  97.                     alphaIndexer.put(name, i); 
  98.                 } 
  99.             } 
  100.             Set<String> sectionLetters = alphaIndexer.keySet(); 
  101.             ArrayList<String> sectionList = new ArrayList<String>( 
  102.                     sectionLetters); 
  103.             Collections.sort(sectionList); 
  104.             sections = new String[sectionList.size()]; 
  105.             sectionList.toArray(sections); 
  106.         } 
  107.         @Override 
  108.         public int getCount() { 
  109.             return list.size(); 
  110.         } 
  111.         @Override 
  112.         public Object getItem(int position) { 
  113.             return list.get(position); 
  114.         } 
  115.         @Override 
  116.         public long getItemId(int position) { 
  117.             return position; 
  118.         } 
  119.         @Override 
  120.         public View getView(int position, View convertView, ViewGroup parent) { 
  121.             ViewHolder holder; 
  122.             if (convertView == null) { 
  123.                 convertView = inflater.inflate(R.layout.list_item,null); 
  124.                 holder = new ViewHolder(); 
  125.                 holder.alpha = (TextView) convertView.findViewById(R.id.alpha); 
  126.                 holder.name = (TextView) convertView.findViewById(R.id.name); 
  127.                 holder.number = (TextView) convertView 
  128.                         .findViewById(R.id.number); 
  129.                 convertView.setTag(holder); 
  130.             } else { 
  131.                 holder = (ViewHolder) convertView.getTag(); 
  132.             } 
  133.             ContentValues cv = list.get(position); 
  134.             String name = cv.getAsString(NAME); 
  135.             String number = cv.getAsString(NUMBER); 
  136.             holder.name.setText(name); 
  137.             holder.number.setText(number); 
  138.             // 目前聯系人的sortKey 
  139.             String currentStr = getAlpha(list.get(position).getAsString( 
  140.                     SORT_KEY)); 
  141.             // 上一個聯系人的sortKey 
  142.             String previewStr = (position - 1) >= 0 ? getAlpha(list.get( 
  143.                     position - 1).getAsString(SORT_KEY)) : " "; 
  144.             if (!previewStr.equals(currentStr)) {// 目前聯系人的sortKey!=上一個聯系人的sortKey,說明目前聯系人是新組。 
  145.                 holder.alpha.setVisibility(View.VISIBLE); 
  146.                 holder.alpha.setText(currentStr); 
  147.             } else { 
  148.                 holder.alpha.setVisibility(View.GONE); 
  149.             } 
  150.             return convertView; 
  151.         } 
  152.         @Override 
  153.         public int getPositionForSection(int section) { 
  154.             String later = sections[section]; 
  155.             return alphaIndexer.get(later); 
  156.         } 
  157.         @Override 
  158.         public int getSectionForPosition(int position) { 
  159.             String key = getAlpha(list.get(position).getAsString(SORT_KEY)); 
  160.             for (int i = 0; i < sections.length; i++) { 
  161.                 if (sections[i].equals(key)) { 
  162.                     return i; 
  163.                 } 
  164.             } 
  165.             return 0; 
  166.         } 
  167.         @Override 
  168.         public Object[] getSections() { 
  169.             return sections; 
  170.         } 
  171.     } 
  172.     private String getAlpha(String str) { 
  173.         if (str == null) { 
  174.             return "#"; 
  175.         } 
  176.         if (str.trim().length() == 0) { 
  177.             return "#"; 
  178.         } 
  179.         char c = str.trim().substring(0, 1).charAt(0); 
  180.         // 正規表達式,判斷首字母是否是英文字母 
  181.         Pattern pattern = Pattern.compile("^[A-Za-z]+{1}quot;); 
  182.         if (pattern.matcher(c + "").matches()) { 
  183.             return (c + "").toUpperCase(); // 大寫輸出 
  184.         } else { 
  185.             return "#"; 
  186.         } 
  187.     } 

2.布局檔案

2.1.main.xml

[html] view plain copy print ?

  1. <?xmlversion="1.0"encoding="utf-8"?> 
  2. <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" 
  3.     android:layout_width="fill_parent" 
  4.     android:layout_height="fill_parent" 
  5.     android:orientation="vertical"> 
  6.     <ListView 
  7.         android:id="@+id/listView" 
  8.         android:layout_width="fill_parent" 
  9.         android:layout_height="fill_parent" 
  10.         android:fastScrollEnabled="true"/> 
  11. </LinearLayout> 

2.2.list_item.xml

[html] view plain copy print ?

  1. <?xmlversion="1.0"encoding="utf-8"?> 
  2. <RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android" 
  3.     android:layout_width="match_parent" 
  4.     android:layout_height="match_parent"> 
  5.     <!-- 首字母 --> 
  6.     <TextView 
  7.         android:id="@+id/alpha" 
  8.         android:layout_width="fill_parent" 
  9.         android:layout_height="wrap_content" 
  10.         android:background="#333333" 
  11.         android:paddingLeft="10dip" 
  12.         android:textColor="#FFFFFF" 
  13.         android:visibility="gone"/> 
  14.     <!-- 聯系人資訊 --> 
  15.     <ImageView 
  16.         android:id="@+id/imageView" 
  17.         android:layout_width="wrap_content" 
  18.         android:layout_height="wrap_content" 
  19.         android:layout_alignParentLeft="true" 
  20.         android:layout_below="@id/alpha" 
  21.         android:src="@drawable/ic_launcher"/> 
  22.     <TextView 
  23.         android:id="@+id/name" 
  24.         android:layout_width="wrap_content" 
  25.         android:layout_height="wrap_content" 
  26.         android:layout_alignTop="@id/imageView" 
  27.         android:layout_marginLeft="2.0dip" 
  28.         android:layout_marginRight="5.0dip" 
  29.         android:layout_marginTop="6.0dip" 
  30.         android:layout_toRightOf="@id/imageView" 
  31.         android:singleLine="true" 
  32.         android:textAppearance="?android:textAppearanceMedium"/> 
  33.     <TextView 
  34.         android:id="@+id/number" 
  35.         android:layout_width="wrap_content" 
  36.         android:layout_height="wrap_content" 
  37.         android:layout_alignLeft="@id/name" 
  38.         android:layout_alignWithParentIfMissing="true" 
  39.         android:layout_below="@id/name" 
  40.         android:ellipsize="marquee" 
  41.         android:singleLine="true" 
  42.         android:textAppearance="?android:textAppearanceSmall"/> 
  43. </RelativeLayout> 

3.效果圖

Android之實作系統聯系人軟體的分組和字母提示效果