Android联系人按拼音排序以及按汉字首字母或全拼搜索

转:http://blog.csdn.net/csuhanyong/article/details/6120935


今天用了整整一下午去捣鼓这块,为什么模拟器上可以按拼音排序,中英文混排,及按字母搜索联系人,但到了开发板(平台是根据android2.2改过的)上就怎么不行了呢,虽然现在还没有解决,但也是知道了问题所在,离解决之路也就不远了

好吧,现在就解释下android2.2是怎么按拼音排序的。

首先我们来看下android.2自带通讯录的数据库文件contacts2.db的raw_contacts表。用sqlitedbviewer工具打开后可以看到有这么一个字段:sort_key(sort_key_alt与之相似,只不过是英文环境下有个按given name还是first name排序的问题)。

正常状况下,我们新建一个联系人的话,如果是英文,则sort_key与display_name字段显示相同,如果输入姓名是中文,如“你好”,sort_key则会显示“ni你hao好”,这样开发者既可以根据此字段按拼音排序,中英文混排,以及按拼音搜索联系人拉。

现在就说下,android是如何将中文名的联系人转化为拼音存到sort_key里面的:


[java] view plain copy
  1. if(displayNameStyle==FullNameStyle.CHINESE||
  2. displayNameStyle==FullNameStyle.CJK){
  3. sortKeyPrimary=sortKeyAlternative=
  4. ContactLocaleUtils.getIntanc).getSortKe(displayNamePrimary,displayNameStyle);}

这段代码是运行在contactsprovi2.Java的updateRawContactDisplayName()方法里面,这段代码我们用到了ContactLocaleUtils.java这个类,所以我们进入它以后最显眼的就是ChineseContactUtils这个ContactLocaleUtils的子类,它重写了ContactLocaleUtils的getSortKey()方法,如下:

[java] view plain copy
  1. publicStringgetSortKey(StringdisplayName){
  2. ArrayList<Token>tokens=HanziToPinyin.getInstance().get(displayName);
  3. if(tokens!=null&&tokens.size()>0){
  4. StringBuildersb=newStringBuilder();
  5. for(Tokentoken:tokens){
  6. //PutChinesecharacter'spinyin,thenproceedwiththe
  7. //characteritself.
  8. if(Token.PINYIN==token.type){
  9. if(sb.length()>0){
  10. sb.append('');
  11. }
  12. sb.append(token.target);
  13. sb.append('');
  14. sb.append(token.source);
  15. }else{
  16. if(sb.length()>0){
  17. sb.append('');
  18. }
  19. sb.append(token.source);
  20. }
  21. }
  22. returnsb.toString();
  23. }
  24. returnsuper.getSortKey(displayName);
  25. }

首先我们看ArrayList<Token> tokens = HanziToPinyin.getInstance().get(displayName);,因为其他的无非就是插入格式的问题,我们暂时不用看。

android如何将汉字转为拼音的?这就用到了HanziToPinyin这个类,好吧,我们先看下HanziToPinyin的getInstance()方法:

[java] view plain copy
  1. publicstaticHanziToPinyingetInstance(){
  2. synchronized(HanziToPinyin.class){
  3. if(sInstance!=null){
  4. returnsInstance;
  5. }
  6. //Checkifzh_CNcollationdataisavailable
  7. finalLocalelocale[]=Collator.getAvailableLocales();
  8. for(inti=0;i<locale.length;i++){
  9. if(locale[i].equals(Locale.CHINA)){
  10. sInstance=newHanziToPinyin(true);
  11. returnsInstance;
  12. }
  13. }
  14. Log.w(TAG,"ThereisnoChinesecollator,HanziToPinyinisdisabled");
  15. sInstance=newHanziToPinyin(false);
  16. returnsInstance;
  17. }
  18. }

现在说下我的开发板为什么不能转拼音;就是因为final Locale locale[] = Collator.getAvailableLocales()的Locale没有一项equals(Locale.CHINA),所以到时候解决了这项,联系人的按拼音排序也就解决了,如果大家不想用系统自带的,自己可以下载个pinyin4j.jar包自己实现吧。

好吧,继续:

看方法名也只到,这个方法返回一个HanziToPinyin实例,我仔细研究了HanziToPinyin的构造方法,无论纯如的布尔值是false还是true都不影响,返回的都一样,只不过这个方法的Log.w(TAG, "There is no Chinese collator, HanziToPinyin is disabled");可以提示是否支持汉字转拼音,如果不能,android就会将displayname原封不动的插入sort_key里面,如果能,就是刚才我说的如“你好”,sort_key则会显示“ni你hao好”,这种形式,具体的如何转拼音就是get()方法拉,直接插代码:

[java] view plain copy
  1. publicArrayList<Token>get(finalStringinput){
  2. ArrayList<Token>tokens=newArrayList<Token>();
  3. if(!mHasChinaCollator||TextUtils.isEmpty(input)){
  4. //returnemptytokens.
  5. returntokens;
  6. }
  7. finalintinputLength=input.length();
  8. finalStringBuildersb=newStringBuilder();
  9. inttokenType=Token.LATIN;
  10. //Gothroughtheinput,createanewtokenwhen
  11. //a.Tokentypechanged
  12. //b.GetthePinyinofcurrentcharater.
  13. //c.currentcharacterisspace.
  14. for(inti=0;i<inputLength;i++){
  15. finalcharcharacter=input.charAt(i);
  16. if(character==''){
  17. if(sb.length()>0){
  18. addToken(sb,tokens,tokenType);
  19. }
  20. }elseif(character<256){
  21. if(tokenType!=Token.LATIN&&sb.length()>0){
  22. addToken(sb,tokens,tokenType);
  23. }
  24. tokenType=Token.LATIN;
  25. sb.append(character);
  26. }elseif(character<FIRST_UNIHAN){
  27. if(tokenType!=Token.UNKNOWN&&sb.length()>0){
  28. addToken(sb,tokens,tokenType);
  29. }
  30. tokenType=Token.UNKNOWN;
  31. sb.append(character);
  32. }else{
  33. Tokent=getToken(character);
  34. if(t.type==Token.PINYIN){
  35. if(sb.length()>0){
  36. addToken(sb,tokens,tokenType);
  37. }
  38. tokens.add(t);
  39. tokenType=Token.PINYIN;
  40. }else{
  41. if(tokenType!=t.type&&sb.length()>0){
  42. addToken(sb,tokens,tokenType);
  43. }
  44. tokenType=t.type;
  45. sb.append(character);
  46. }
  47. }
  48. }
  49. if(sb.length()>0){
  50. addToken(sb,tokens,tokenType);
  51. }
  52. returntokens;
  53. }

你可能感兴趣的:(android)