Android之实现系统联系人软件的分组和字母提示效果

联系人分章节显示以及ListView快速滑动显示联系人首字母例子,查阅网上很多这样的例子后,发现普遍是从系统源码里面抽取的,而且普遍比较复杂,这里做了精简,扩展性较强,移植起来非常方便。


1.FastContactSearchDemoActivity.java

[javascript]  view plain copy print ?
  1. package com.zhf.FastContactSearchDemo; 
  2.  
  3. import java.util.ArrayList; 
  4. import java.util.Collections; 
  5. import java.util.HashMap; 
  6. import java.util.List; 
  7. import java.util.Set; 
  8. import java.util.regex.Pattern; 
  9. import android.app.Activity; 
  10. import android.content.AsyncQueryHandler; 
  11. import android.content.ContentResolver; 
  12. import android.content.ContentValues; 
  13. import android.content.Context; 
  14. import android.database.Cursor; 
  15. import android.net.Uri; 
  16. import android.os.Bundle; 
  17. import android.view.LayoutInflater; 
  18. import android.view.View; 
  19. import android.view.ViewGroup; 
  20. import android.widget.BaseAdapter; 
  21. import android.widget.ListView; 
  22. import android.widget.SectionIndexer; 
  23. import android.widget.TextView; 
  24.  
  25. /**
  26. * 联系人分章节显示以及ListView快速滑动显示联系人首字母例子
  27. * 本例来自http://blog.csdn.net/luck_apple/article/details/6741860
  28. * 查阅网上很多这样的例子后,发现普遍是从系统源码里面抽取的,而且普遍比较复杂,这里做了精简,扩展性较强,移植起来非常方便。
  29. * @author hiphonezhu@sina.com
  30. *
  31. */ 
  32. public class FastContactSearchDemoActivityextends Activity { 
  33.     private BaseAdapter adapter; 
  34.     private ListView personList; 
  35.     private AsyncQueryHandler asyncQuery; 
  36.     private staticfinal String NAME ="name", NUMBER ="number"
  37.             SORT_KEY = "sort_key"
  38.  
  39.     @Override 
  40.     public void onCreate(Bundle savedInstanceState) { 
  41.         super.onCreate(savedInstanceState); 
  42.         setContentView(R.layout.main); 
  43.         personList = (ListView) findViewById(R.id.listView); 
  44.         asyncQuery = new MyAsyncQueryHandler(getContentResolver()); 
  45.     } 
  46.  
  47.     @Override 
  48.     protected void onResume() { 
  49.         super.onResume(); 
  50.         Uri uri = Uri.parse("content://com.android.contacts/data/phones"); // 联系人的Uri 
  51.         String[] projection = { "_id","display_name","data1","sort_key" };// 查询的列 
  52.         asyncQuery.startQuery(0, null, uri, projection,null,null
  53.                 "sort_key COLLATE LOCALIZED asc");// 按照sort_key升序查询 
  54.     } 
  55.  
  56.     /**
  57.      * 数据库异步查询类AsyncQueryHandler
  58.      *
  59.      * @author administrator
  60.      *
  61.      */ 
  62.     private class MyAsyncQueryHandlerextends AsyncQueryHandler { 
  63.  
  64.         public MyAsyncQueryHandler(ContentResolver cr) { 
  65.             super(cr); 
  66.  
  67.         } 
  68.  
  69.         /**
  70.          * 查询结束的回调函数
  71.          */ 
  72.         @Override 
  73.         protected void onQueryComplete(int token, Object cookie, Cursor cursor) { 
  74.             if (cursor != null && cursor.getCount() > 0) { 
  75.                 List<ContentValues> list = new ArrayList<ContentValues>(); 
  76.                 cursor.moveToFirst(); 
  77.                 for (int i = 0; i < cursor.getCount(); i++) { 
  78.                     ContentValues cv = new ContentValues(); 
  79.                     cursor.moveToPosition(i); 
  80.                     String name = cursor.getString(1); 
  81.                     String number = cursor.getString(2); 
  82.                     String sortKey = cursor.getString(3); 
  83.  
  84.                     if (number.startsWith("+86")) {// 去除多余的中国地区号码标志,对这个程序没有影响。 
  85.                         cv.put(NAME, name); 
  86.                         cv.put(NUMBER, number.substring(3)); 
  87.                         cv.put(SORT_KEY, sortKey); 
  88.                     } else { 
  89.                         cv.put(NAME, name); 
  90.                         cv.put(NUMBER, number); 
  91.                         cv.put(SORT_KEY, sortKey); 
  92.                     } 
  93.                     list.add(cv); 
  94.                 } 
  95.                 if (list.size() > 0) { 
  96.                     setAdapter(list); 
  97.                 } 
  98.             } 
  99.         } 
  100.  
  101.     } 
  102.  
  103.     private void setAdapter(List<ContentValues> list) { 
  104.         adapter = new ListAdapter(this, list); 
  105.         personList.setAdapter(adapter); 
  106.  
  107.     } 
  108.  
  109.     private staticclass ViewHolder { 
  110.         TextView alpha; 
  111.         TextView name; 
  112.         TextView number; 
  113.     } 
  114.  
  115.     /**
  116.      * 其他项目使用时,只需要传进来一个有序的list即可
  117.      */ 
  118.     private class ListAdapterextends BaseAdapterimplements SectionIndexer { 
  119.         private LayoutInflater inflater; 
  120.         private List<ContentValues> list; 
  121.         private HashMap<String, Integer> alphaIndexer;//保存每个索引在list中的位置【#-0,A-4,B-10】 
  122.         private String[] sections;//每个分组的索引表【A,B,C,F...】 
  123.  
  124.         public ListAdapter(Context context, List<ContentValues> list) { 
  125.             this.inflater = LayoutInflater.from(context); 
  126.             this.list = list; // 该list是已经排序过的集合,有些项目中的数据必须要自己进行排序。 
  127.             this.alphaIndexer =new HashMap<String, Integer>(); 
  128.  
  129.             for (int i =0; i <list.size(); i++) { 
  130.                 String name = getAlpha(list.get(i).getAsString(SORT_KEY)); 
  131.                 if(!alphaIndexer.containsKey(name)){//只记录在list中首次出现的位置 
  132.                     alphaIndexer.put(name, i); 
  133.                 } 
  134.             } 
  135.             Set<String> sectionLetters = alphaIndexer.keySet(); 
  136.             ArrayList<String> sectionList = new ArrayList<String>( 
  137.                     sectionLetters); 
  138.             Collections.sort(sectionList); 
  139.             sections = new String[sectionList.size()]; 
  140.             sectionList.toArray(sections); 
  141.         } 
  142.  
  143.         @Override 
  144.         public int getCount() { 
  145.             return list.size(); 
  146.         } 
  147.  
  148.         @Override 
  149.         public Object getItem(int position) { 
  150.             return list.get(position); 
  151.         } 
  152.  
  153.         @Override 
  154.         public long getItemId(int position) { 
  155.             return position; 
  156.         } 
  157.  
  158.         @Override 
  159.         public View getView(int position, View convertView, ViewGroup parent) { 
  160.             ViewHolder holder; 
  161.  
  162.             if (convertView == null) { 
  163.                 convertView = inflater.inflate(R.layout.list_item,null); 
  164.                 holder = new ViewHolder(); 
  165.                 holder.alpha = (TextView) convertView.findViewById(R.id.alpha); 
  166.                 holder.name = (TextView) convertView.findViewById(R.id.name); 
  167.                 holder.number = (TextView) convertView 
  168.                         .findViewById(R.id.number); 
  169.                 convertView.setTag(holder); 
  170.             } else { 
  171.                 holder = (ViewHolder) convertView.getTag(); 
  172.             } 
  173.             ContentValues cv = list.get(position); 
  174.             String name = cv.getAsString(NAME); 
  175.             String number = cv.getAsString(NUMBER); 
  176.             holder.name.setText(name); 
  177.             holder.number.setText(number); 
  178.  
  179.             // 当前联系人的sortKey 
  180.             String currentStr = getAlpha(list.get(position).getAsString( 
  181.                     SORT_KEY)); 
  182.             // 上一个联系人的sortKey 
  183.             String previewStr = (position - 1) >= 0 ? getAlpha(list.get( 
  184.                     position - 1).getAsString(SORT_KEY)) : " "
  185.             /**
  186.              * 判断显示#、A-Z的TextView隐藏与可见
  187.              */ 
  188.             if (!previewStr.equals(currentStr)) {// 当前联系人的sortKey!=上一个联系人的sortKey,说明当前联系人是新组。 
  189.                 holder.alpha.setVisibility(View.VISIBLE); 
  190.                 holder.alpha.setText(currentStr); 
  191.             } else { 
  192.                 holder.alpha.setVisibility(View.GONE); 
  193.             } 
  194.             return convertView; 
  195.         } 
  196.  
  197.         /*
  198.          * 此方法根据联系人的首字母返回在list中的位置
  199.          */ 
  200.         @Override 
  201.         public int getPositionForSection(int section) { 
  202.             String later = sections[section]; 
  203.             return alphaIndexer.get(later); 
  204.         } 
  205.  
  206.         /*
  207.          * 本例中可以不考虑这个方法
  208.          */ 
  209.         @Override 
  210.         public int getSectionForPosition(int position) { 
  211.             String key = getAlpha(list.get(position).getAsString(SORT_KEY)); 
  212.             for (int i = 0; i < sections.length; i++) { 
  213.                 if (sections[i].equals(key)) { 
  214.                     return i; 
  215.                 } 
  216.             } 
  217.             return 0; 
  218.         } 
  219.  
  220.         @Override 
  221.         public Object[] getSections() { 
  222.             return sections; 
  223.         } 
  224.     } 
  225.  
  226.     /**
  227.      * 提取英文的首字母,非英文字母用#代替
  228.      *
  229.      * @param str
  230.      * @return
  231.      */ 
  232.     private String getAlpha(String str) { 
  233.         if (str == null) { 
  234.             return "#"
  235.         } 
  236.  
  237.         if (str.trim().length() == 0) { 
  238.             return "#"
  239.         } 
  240.  
  241.         char c = str.trim().substring(0, 1).charAt(0); 
  242.         // 正则表达式,判断首字母是否是英文字母 
  243.         Pattern pattern = Pattern.compile("^[A-Za-z]+{1}quot;); 
  244.         if (pattern.matcher(c + "").matches()) { 
  245.             return (c + "").toUpperCase(); // 大写输出 
  246.         } else { 
  247.             return "#"
  248.         } 
  249.     } 

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.  
  7.     <ListView 
  8.         android:id="@+id/listView" 
  9.         android:layout_width="fill_parent" 
  10.         android:layout_height="fill_parent" 
  11.         android:fastScrollEnabled="true"/> 
  12.  
  13. </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.     <!-- 首字母 --> 
  7.     <TextView 
  8.         android:id="@+id/alpha" 
  9.         android:layout_width="fill_parent" 
  10.         android:layout_height="wrap_content" 
  11.         android:background="#333333" 
  12.         android:paddingLeft="10dip" 
  13.         android:textColor="#FFFFFF" 
  14.         android:visibility="gone"/> 
  15.      
  16.     <!-- 联系人信息 --> 
  17.     <ImageView 
  18.         android:id="@+id/imageView" 
  19.         android:layout_width="wrap_content" 
  20.         android:layout_height="wrap_content" 
  21.         android:layout_alignParentLeft="true" 
  22.         android:layout_below="@id/alpha" 
  23.         android:src="@drawable/ic_launcher"/> 
  24.  
  25.     <TextView 
  26.         android:id="@+id/name" 
  27.         android:layout_width="wrap_content" 
  28.         android:layout_height="wrap_content" 
  29.         android:layout_alignTop="@id/imageView" 
  30.         android:layout_marginLeft="2.0dip" 
  31.         android:layout_marginRight="5.0dip" 
  32.         android:layout_marginTop="6.0dip" 
  33.         android:layout_toRightOf="@id/imageView" 
  34.         android:singleLine="true" 
  35.         android:textAppearance="?android:textAppearanceMedium"/> 
  36.  
  37.     <TextView 
  38.         android:id="@+id/number" 
  39.         android:layout_width="wrap_content" 
  40.         android:layout_height="wrap_content" 
  41.         android:layout_alignLeft="@id/name" 
  42.         android:layout_alignWithParentIfMissing="true" 
  43.         android:layout_below="@id/name" 
  44.         android:ellipsize="marquee" 
  45.         android:singleLine="true" 
  46.         android:textAppearance="?android:textAppearanceSmall"/> 
  47.  
  48. </RelativeLayout> 

3.效果图

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值