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

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

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

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

 

 

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

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

 


if (displayNameStyle == FullNameStyle.CHINESE || displayNameStyle == FullNameStyle.CJK) { sortKeyPrimary = sortKeyAlternative = ContactLocaleUtils.getIntanc).getSortKe(displayNamePrimary, displayNameStyle);}  

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

public String getSortKey(String displayName) { ArrayList tokens = HanziToPinyin.getInstance().get(displayName); if (tokens != null && tokens.size() > 0) { StringBuilder sb = new StringBuilder(); for (Token token : tokens) { // Put Chinese character's pinyin, then proceed with the // character itself. if (Token.PINYIN == token.type) { if (sb.length() > 0) { sb.append(' '); } sb.append(token.target); sb.append(' '); sb.append(token.source); } else { if (sb.length() > 0) { sb.append(' '); } sb.append(token.source); } } return sb.toString(); } return super.getSortKey(displayName); }         

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

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

public static HanziToPinyin getInstance() { synchronized(HanziToPinyin.class) { if (sInstance != null) { return sInstance; } // Check if zh_CN collation data is available final Locale locale[] = Collator.getAvailableLocales(); for (int i = 0; i < locale.length; i++) { if (locale[i].equals(Locale.CHINA)) { sInstance = new HanziToPinyin(true); return sInstance; } } Log.w(TAG, "There is no Chinese collator, HanziToPinyin is disabled"); sInstance = new HanziToPinyin(false); return sInstance; } }

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

 

 

 

 

 

 public ArrayList get(final String input) { ArrayList tokens = new ArrayList(); if (!mHasChinaCollator || TextUtils.isEmpty(input)) { // return empty tokens. return tokens; } final int inputLength = input.length(); final StringBuilder sb = new StringBuilder(); int tokenType = Token.LATIN; // Go through the input, create a new token when // a. Token type changed // b. Get the Pinyin of current charater. // c. current character is space. for (int i = 0; i < inputLength; i++) { final char character = input.charAt(i); if (character == ' ') { if (sb.length() > 0) { addToken(sb, tokens, tokenType); } } else if (character < 256) { if (tokenType != Token.LATIN && sb.length() > 0) { addToken(sb, tokens, tokenType); } tokenType = Token.LATIN; sb.append(character); } else if (character < FIRST_UNIHAN) { if (tokenType != Token.UNKNOWN && sb.length() > 0) { addToken(sb, tokens, tokenType); } tokenType = Token.UNKNOWN; sb.append(character); } else { Token t = getToken(character); if (t.type == Token.PINYIN) { if (sb.length() > 0) { addToken(sb, tokens, tokenType); } tokens.add(t); tokenType = Token.PINYIN; } else { if (tokenType != t.type && sb.length() > 0) { addToken(sb, tokens, tokenType); } tokenType = t.type; sb.append(character); } } } if (sb.length() > 0) { addToken(sb, tokens, tokenType); } return tokens; }

 

 

 

你可能感兴趣的:(android)