关闭

拼音排序

标签: androidjava
345人阅读 评论(0) 收藏 举报
分类:

今天用了整整一下午去捣鼓这块,为 什么模拟器上可以按拼音排序,中英文混排,及按字母搜索联系人,但到了开发板(平台是根据 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 里面的:

 


  1. if  (displayNameStyle == FullNameStyle.CHINESE ||  
  2.                    displayNameStyle == FullNameStyle.CJK) {  
  3.     sortKeyPrimary = sortKeyAlternative =  
  4.                     ContactLocaleUtils.getIntanc).getSortKe(displayNamePrimary, displayNameStyle);}  
  1.  if   
  2. (displayNameStyle == FullNameStyle.CHINESE ||  
  3.                     displayNameStyle == FullNameStyle.CJK) {  
  4.      sortKeyPrimary = sortKeyAlternative =  
  5.                        
  6. ContactLocaleUtils.getIntanc).getSortKe(displayNamePrimary,   
  7. displayNameStyle);}  
  

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

  1. public  String getSortKey(String displayName) {  
  2.   
  3.             ArrayList<Token> tokens = HanziToPinyin.getInstance().get(displayName);  
  4.   
  5.             if  (tokens !=  null  && tokens.size() >  0 ) {  
  6.   
  7.                 StringBuilder sb = new  StringBuilder();  
  8.   
  9.                 for  (Token token : tokens) {  
  10.   
  11.                     // Put Chinese character's pinyin, then proceed with the   
  12.   
  13.                     // character itself.   
  14.   
  15.                     if  (Token.PINYIN == token.type) {  
  16.   
  17.                         if  (sb.length() >  0 ) {  
  18.   
  19.                             sb.append(' ' );  
  20.   
  21.                         }  
  22.   
  23.                         sb.append(token.target);  
  24.   
  25.                         sb.append(' ' );  
  26.   
  27.                         sb.append(token.source);  
  28.   
  29.                     } else  {  
  30.   
  31.                         if  (sb.length() >  0 ) {  
  32.   
  33.                             sb.append(' ' );  
  34.   
  35.                         }  
  36.   
  37.                         sb.append(token.source);  
  38.   
  39.                     }  
  40.   
  41.                 }  
  42.   
  43.                 return  sb.toString();  
  44.   
  45.             }  
  46.   
  47.             return   super .getSortKey(displayName);  
  48.   
  49. }  
  1. public  
  2.  String getSortKey(String displayName) {  
  3.             ArrayList<Token> tokens =   
  4. HanziToPinyin.getInstance().get(displayName);  
  5.             if (tokens != null && tokens.size() > 0) {  
  6.                 StringBuilder sb = new StringBuilder();  
  7.                 for (Token token : tokens) {  
  8.                     // Put Chinese character's pinyin, then proceed with  
  9.  the  
  10.                     // character itself.  
  11.                     if (Token.PINYIN == token.type) {  
  12.                         if (sb.length() > 0) {  
  13.                             sb.append(' ');  
  14.                         }  
  15.                         sb.append(token.target);  
  16.                         sb.append(' ');  
  17.                         sb.append(token.source);  
  18.                     } else {  
  19.                         if (sb.length() > 0) {  
  20.                             sb.append(' ');  
  21.                         }  
  22.                         sb.append(token.source);  
  23.                     }  
  24.                 }  
  25.                 return sb.toString();  
  26.             }  
  27.             return super.getSortKey(displayName);  
  28. }  
        

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

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

 

  1. public   static  HanziToPinyin getInstance() {  
  2.   
  3.     synchronized (HanziToPinyin. class ) {  
  4.   
  5.         if  (sInstance !=  null ) {  
  6.   
  7.             return  sInstance;  
  8.   
  9.         }  
  10.   
  11.         // Check if zh_CN collation data is available   
  12.   
  13.         final  Locale locale[] = Collator.getAvailableLocales();  
  14.   
  15.         for  ( int  i =  0 ; i < locale.length; i++) {  
  16.   
  17.             if  (locale[i].equals(Locale.CHINA)) {  
  18.   
  19.                 sInstance = new  HanziToPinyin( true );  
  20.   
  21.                 return  sInstance;  
  22.   
  23.             }  
  24.   
  25.         }  
  26.   
  27.         Log.w(TAG, "There is no Chinese collator, HanziToPinyin is disabled" );  
  28.   
  29.         sInstance = new  HanziToPinyin( false );  
  30.   
  31.         return  sInstance;  
  32.   
  33.     }  
  34.   
  35. }  
  1.      
  2.  public static HanziToPinyin getInstance() {  
  3.         synchronized(HanziToPinyin.class) {  
  4.             if (sInstance != null) {  
  5.                 return sInstance;  
  6.             }  
  7.             // Check if zh_CN collation data is available  
  8.             final Locale locale[] = Collator.getAvailableLocales();  
  9.             for (int i = 0; i < locale.length; i++) {  
  10.                 if (locale[i].equals(Locale.CHINA)) {  
  11.                     sInstance = new HanziToPinyin(true);  
  12.                     return sInstance;  
  13.                 }  
  14.             }  
  15.             Log.w(TAG, "There is no Chinese collator, HanziToPinyin is   
  16. disabled");  
  17.             sInstance = new HanziToPinyin(false);  
  18.             return sInstance;  
  19.         }  
  20.     }  

现在说下我的开发板为什么不能 转拼音;就是因为 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 ()方法拉,直接插代码:

 

 

 

  1. public  ArrayList<Token> get( final  String input) {  
  2.         ArrayList<Token> tokens = new  ArrayList<Token>();  
  3.         if  (!mHasChinaCollator || TextUtils.isEmpty(input)) {  
  4.             // return empty tokens.   
  5.             return  tokens;  
  6.         }  
  7.         final   int  inputLength = input.length();  
  8.         final  StringBuilder sb =  new  StringBuilder();  
  9.         int  tokenType = Token.LATIN;  
  10.         // Go through the input, create a new token when   
  11.         // a. Token type changed   
  12.         // b. Get the Pinyin of current charater.   
  13.         // c. current character is space.   
  14.         for  ( int  i =  0 ; i < inputLength; i++) {  
  15.             final   char  character = input.charAt(i);  
  16.             if  (character ==  ' ' ) {  
  17.                 if  (sb.length() >  0 ) {  
  18.                     addToken(sb, tokens, tokenType);  
  19.                 }  
  20.             } else   if  (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.             } else   if  (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.                 Token t = 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.         return  tokens;  
  53.     }  
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:23918次
    • 积分:347
    • 等级:
    • 排名:千里之外
    • 原创:4篇
    • 转载:35篇
    • 译文:2篇
    • 评论:2条
    最新评论
  • Device 分析

    lccly: hi 我最近在看这个库。有个地方感觉写的有问题。我贴出来,麻烦给解答一下。这里为什么会启动一个循环在...

  • Android AIDL使用详解

    ldwying: 很喜欢博主的文章,刚刚用豆约翰博客备份专家备份了您的全部博文。