《android2.2自带通讯录》之联系人按拼音排序以及按汉字首字母或全拼搜索

原文链接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里面的:

 


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

这段代码是运行在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. }  
        

   首先我们看 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. }  

现在说下我的开发板为什么不能转拼音;就是因为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.     }  



  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要实现通讯录按名字首字母排序分组,可以按照以下步骤进行: 1. 获取通讯录数据,并将每个联系人的名字转换为拼音。 2. 根据拼音首字母联系人进行分组。 3. 对每个分组内的联系人按照名字进行排序。 4. 在页面上渲染每个分组及其对应的联系人。 以下是一个简单的实现示例: 1. 使用 pinyin 库将联系人名字转换为拼音: ```js import pinyin from 'pinyin'; const contacts = [ { name: '张三', phone: '123456789' }, { name: '李四', phone: '987654321' }, // ... ]; const pinyinContacts = contacts.map(contact => { const pinyinName = pinyin(contact.name, { style: pinyin.STYLE_FIRST_LETTER }).join(''); return { ...contact, pinyinName }; }); ``` 2. 根据拼音首字母联系人进行分组: ```js const groupedContacts = pinyinContacts.reduce((groups, contact) => { const firstLetter = contact.pinyinName[0].toUpperCase(); if (!groups[firstLetter]) { groups[firstLetter] = []; } groups[firstLetter].push(contact); return groups; }, {}); ``` 3. 对每个分组内的联系人按照名字进行排序: ```js Object.keys(groupedContacts).forEach(key => { groupedContacts[key].sort((a, b) => a.name.localeCompare(b.name)); }); ``` 4. 在页面上渲染每个分组及其对应的联系人: ```html <template> <div> <div v-for="(contacts, letter) in groupedContacts" :key="letter"> <h2>{{ letter }}</h2> <ul> <li v-for="contact in contacts" :key="contact.phone">{{ contact.name }}</li> </ul> </div> </div> </template> <script> export default { data() { return { groupedContacts: {}, }; }, mounted() { // 获取联系人数据并处理分组排序 // ... this.groupedContacts = groupedContacts; }, }; </script> ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值