汉字转拼音

app中有许多场景要对汉字排序,例如通讯录姓名、商品名称、城市名称等等,这些汉字词汇通常是按照拼音排序,所以产生了把汉字转换为拼音的需求。

Android自带库

Android自带的联系人应用,就支持对联系人按照姓名排序,内置汉字转拼音的源码位于路径“packages\providers\ContactsProvider\src\com\android\providers\contacts\HanziToPinyin.java”。该工具类早期的源码,直接把字符集合写在java文件中,这种做法在4.2以上版本不能正常工作。4.2以上的工具源码改为调用底层的jni接口,具体说来,便是HanziToPinyin.java引用了核心库libcore.icu的Transliterator类,Transliterator内部有提供数个native方法。

不管是HanziToPinyin类还是Transliterator类,都属于系统源码,不属于sdk源码,也就是说,app开发无法直接调用这两个类的方法。只能是把这两个类的java文件直接复制到app工程中,才能正常调用其中的api。同时注意,Transliterator.java必须放在名称是libcore.icu的包路径下,因为该类引用了jni接口,而jni接口要求包名、类名、方法名都保持一致才能正常运行,jni的详细说明参见《 Android开发笔记(六十九)JNI实战》。

下面是HanziToPinyin.java的源码:

import android.text.TextUtils;
import android.util.Log;import java.util.ArrayList;import libcore.icu.Transliterator;public class HanziToPinyin {private static final String TAG = "HanziToPinyin";private static HanziToPinyin sInstance;private Transliterator mPinyinTransliterator;private Transliterator mAsciiTransliterator;public static class Token {public static final String SEPARATOR = " ";public static final int LATIN = 1;public static final int PINYIN = 2;public static final int UNKNOWN = 3;public Token() {}public Token(int type, String source, String target) {this.type = type;this.source = source;this.target = target;}public int type;public String source;public String target;}private HanziToPinyin() {try {mPinyinTransliterator = new Transliterator("Han-Latin/Names; Latin-Ascii; Any-Upper");mAsciiTransliterator = new Transliterator("Latin-Ascii");} catch (RuntimeException e) {Log.w(TAG, "Han-Latin/Names transliterator data is missing," + " HanziToPinyin is disabled");}}public boolean hasChineseTransliterator() {return mPinyinTransliterator != null;}public static HanziToPinyin getInstance() {synchronized (HanziToPinyin.class) {if (sInstance == null) {sInstance = new HanziToPinyin();}return sInstance;}}private void tokenize(char character, Token token) {token.source = Character.toString(character);// ASCIIif (character < 128) {token.type = Token.LATIN;token.target = token.source;return;}// Extended Latin. Transcode these to ASCII equivalentsif (character < 0x250 || (0x1e00 <= character && character < 0x1eff)) {token.type = Token.LATIN;token.target = mAsciiTransliterator == null ? token.source :mAsciiTransliterator.transliterate(token.source);return;}token.type = Token.PINYIN;token.target = mPinyinTransliterator.transliterate(token.source);if (TextUtils.isEmpty(token.target) ||TextUtils.equals(token.source, token.target)) {token.type = Token.UNKNOWN;token.target = token.source;}}public String transliterate(final String input) {if (!hasChineseTransliterator() || TextUtils.isEmpty(input)) {return null;}return mPinyinTransliterator.transliterate(input);}public ArrayList<Token> getTokens(final String input) {ArrayList<Token> tokens = new ArrayList<Token>();if (!hasChineseTransliterator() || TextUtils.isEmpty(input)) {return tokens;}final int inputLength = input.length();final StringBuilder sb = new StringBuilder();int tokenType = Token.LATIN;Token token = new Token();for (int i = 0; i < inputLength; i++) {final char character = input.charAt(i);if (Character.isSpaceChar(character)) {if (sb.length() > 0) {addToken(sb, tokens, tokenType);}} else {tokenize(character, token);if (token.type == Token.PINYIN) {if (sb.length() > 0) {addToken(sb, tokens, tokenType);}tokens.add(token);token = new Token();} else {if (tokenType != token.type && sb.length() > 0) {addToken(sb, tokens, tokenType);}sb.append(token.target);}tokenType = token.type;}}if (sb.length() > 0) {addToken(sb, tokens, tokenType);}return tokens;}private void addToken(final StringBuilder sb, final ArrayList<Token> tokens, final int tokenType) {String str = sb.toString();tokens.add(new Token(tokenType, str, str));sb.setLength(0);}
}

下面是Transliterator.java的源码:

package libcore.icu;
/*** Exposes icu4c's Transliterator.*/
public final class Transliterator {private long peer;/*** Creates a new Transliterator for the given id.*/public Transliterator(String id) {peer = create(id);}@Override protected synchronized void finalize() throws Throwable {try {destroy(peer);peer = 0;} finally {super.finalize();}}/*** Returns the ids of all known transliterators.*/public static native String[] getAvailableIDs();/*** Transliterates the specified string.*/public String transliterate(String s) {return transliterate(peer, s);}private static native long create(String id);private static native void destroy(long peer);private static native String transliterate(long peer, String s);
}

下面是调用HanziToPinyin的代码例子:

String pinyin = HanziToPinyin.getInstance().transliterate("我爱你中国");

pinyin4j

pinyin4j是java版本的拼音库,可直接拿到android上使用。pinyin4j与Android自带库相比,多出的功能有:
1、支持展示多音字的不同拼音;
2、支持显示汉字拼音的四个声调;

pinyin4j中常用的就是两个类,一个类HanyuPinyinOutputFormat是用来设置拼音格式的,另一个类PinyinHelper是用来进行转换操作的。

下面是HanyuPinyinOutputFormat的常用方法说明:
setCaseType : 设置拼音的大小写。HanyuPinyinCaseType.UPPERCASE表示大写,HanyuPinyinCaseType.LOWERCASE表示小写。
setToneType : 设置拼音的声调形式。HanyuPinyinToneType.WITHOUT_TONE表示不标声调,HanyuPinyinToneType.WITH_TONE_NUMBER表示在拼音末尾标注数字1-4表示四个声调,HanyuPinyinToneType.WITH_TONE_MARK表示在拼音上方标注四个声调的符号。
setVCharType : 设置特殊拼音ü的的显示格式。HanyuPinyinVCharType.WITH_V表示ü显示为字符v,HanyuPinyinVCharType.WITH_U_AND_COLON表示ü显示为字符u:,HanyuPinyinVCharType.WITH_U_UNICODE表示ü显示为字符ü。
注意:当声调形式设置为符号声调时,setVCharType只能选择HanyuPinyinVCharType.WITH_U_UNICODE,否则运行时会报错“net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination: tone marks cannot be added to v or u:”。

下面是PinyinHelper的常用方法说明:
toHanyuPinyinStringArray : 转为汉字拼音。中国大陆使用
toTongyongPinyinStringArray : 转为通用拼音。中国台湾使用
toWadeGilesPinyinStringArray : 转为威妥玛拼音。
toMPS2PinyinStringArray : 转为注音符号拼音。
toYalePinyinStringArray : 转为耶魯拼音。
toGwoyeuRomatzyhStringArray : 转为国语罗马字。

下面是pinyin4j的一个使用例子代码:

import java.util.HashSet;
import java.util.Locale;
import java.util.Set;import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;public class pinyin4j {public static String makeStringByStringSet(Set<String> stringSet) {StringBuilder str = new StringBuilder();int i = 0;for (String s : stringSet) {if (i == stringSet.size() - 1) {str.append(s);} else {str.append(s + ",");}i++;}return str.toString().toLowerCase(Locale.getDefault());}public static Set<String> getPinyin(String src) {if (src != null && !src.trim().equalsIgnoreCase("")) {char[] srcChar;srcChar = src.toCharArray();// 汉语拼音格式输出类HanyuPinyinOutputFormat hanYuPinOutputFormat = new HanyuPinyinOutputFormat();// 输出设置,大小写,音标方式等hanYuPinOutputFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);hanYuPinOutputFormat.setToneType(HanyuPinyinToneType.WITH_TONE_MARK);hanYuPinOutputFormat.setVCharType(HanyuPinyinVCharType.WITH_U_UNICODE);String[][] temp = new String[src.length()][];for (int i = 0; i < srcChar.length; i++) {char c = srcChar[i];// 是中文或者a-z或者A-Z转换拼音(我的需求,是保留中文或者a-z或者A-Z)if (String.valueOf(c).matches("[\\u4E00-\\u9FA5]+")) {try {temp[i] = PinyinHelper.toHanyuPinyinStringArray(srcChar[i], hanYuPinOutputFormat);} catch (BadHanyuPinyinOutputFormatCombination e) {e.printStackTrace();}} else if (((int) c >= 65 && (int) c <= 90)|| ((int) c >= 97 && (int) c <= 122)) {temp[i] = new String[] { String.valueOf(srcChar[i]) };} else {temp[i] = new String[] { "" };}}String[] pingyinArray = Exchange(temp);Set<String> pinyinSet = new HashSet<String>();for (int i = 0; i < pingyinArray.length; i++) {pinyinSet.add(pingyinArray[i]);}return pinyinSet;}return null;}public static String[] Exchange(String[][] strJaggedArray) {String[][] temp = DoExchange(strJaggedArray);return temp[0];}private static String[][] DoExchange(String[][] strJaggedArray) {int len = strJaggedArray.length;if (len >= 2) {int len1 = strJaggedArray[0].length;int len2 = strJaggedArray[1].length;int newlen = len1 * len2;String[] temp = new String[newlen];int Index = 0;for (int i = 0; i < len1; i++) {for (int j = 0; j < len2; j++) {temp[Index] = strJaggedArray[0][i] + strJaggedArray[1][j];Index++;}}String[][] newArray = new String[len - 1][];for (int i = 2; i < len; i++) {newArray[i - 1] = strJaggedArray[i];}newArray[0] = temp;return DoExchange(newArray);} else {return strJaggedArray;}}public static String getPinyinFull(String hanzi) {return makeStringByStringSet(getPinyin(hanzi));}}

下面是Android自带库与pinyin4j转换汉字拼音的截图:

国际语言版本

如同很多windows桌面软件一样,Android也支持将应用发布为多语言版本,即随着手机系统设置的语言变化,app也随之显示对应的语言文本。Android支持对app的字符串和图片分别做国际化处理,字符串国际化只要在res下新建对应语言的values目录就好,比如英文环境的目录命名为“values-en”,中文环境的目录命名为“values-zh”。ADT新建Android项目时,会在res目下自动创建默认环境的values目录,如果某个语言环境没有在项目中定义配置,那么也会使用values下的资源。

Android的图片国际化同理,即在res下新建drawable-zh目录,存放中文环境下的图片;新建drawable-en目录,存放英文环境下的图片。不同分辨率的图片也可以按此规则处理,例如drawable-zh-hdpi表示中文环境下高分辨率的图片目录。

下面是Android多国语言的目录命名列表:

中文(中国大陆):values-zh-rCN
中文(中国台湾):values-zh-rTW
中文(中国香港):values-zh-rHK

英文(美国):values-en-rUS
英文(英国):values-en-rGB
英文(澳大利亚):values-en-rAU
英文(加拿大):values-en-rCA
英文(爱尔兰):values-en-rIE
英文(印度):values-en-rIN
英文(新西兰):values-en-rNZ
英文(新加坡):values-en-rSG
英文(南非):values-en-rZA

阿拉伯文(埃及):values-ar-rEG
阿拉伯文(以色列):values-ar-rIL
保加利亚文:  values-bg-rBG
加泰罗尼亚文(西班牙):values-ca-rES
捷克文:values-cs-rCZ
丹麦文:values-da-rDK
德文(奥地利):values-de-rAT
德文(瑞士):values-de-rCH
德文(德国):values-de-rDE
德文(列支敦士登):values-de-rLI
希腊文:values-el-rGR
西班牙文(西班牙):values-es-rES
西班牙文(美国):values-es-rUS
芬兰文:values-fi-rFI
法文(比利时):values-fr-rBE
法文(加拿大):values-fr-rCA
法文(瑞士):values-fr-rCH
法文(法国):values-fr-rFR
希伯来文(以色列):values-iw-rIL
印地文(印度):values-hi-rIN
克罗地亚文:values-hr-rHR
匈牙利文:values-hu-rHU
印度尼西亚文:values-in-rID
意大利文(瑞士):values-it-rCH
意大利文(意大利):values-it-rIT
日文:values-ja-rJP
韩文:values-ko-rKR
立陶宛文:valueslt-rLT
拉脱维亚文:values-lv-rLV
博克马尔文(挪威):values-nb-rNO
荷兰文(比利时):values-nl-BE
荷兰文(荷兰):values-nl-rNL
波兰文:values-pl-rPL
葡萄牙文(巴西):values-pt-rBR
葡萄牙文(葡萄牙):values-pt-rPT
罗马尼亚文:values-ro-rRO
俄文:values-ru-rRU
斯洛伐克文:values-sk-rSK
斯洛文尼亚文:values-sl-rSI
塞尔维亚文:values-sr-rRS
瑞典文:values-sv-rSE
泰文(泰国):values-th-rTH
塔加洛文(菲律宾):values-tl-rPH
土耳其文:values--r-rTR
乌克兰文:values-uk-rUA
越南文:values-vi-rVN

点击下载本文用到的多语言支持的工程代码

点此查看Android开发笔记的完整目录

Android开发笔记(八十三)多语言支持相关推荐

  1. Android开发笔记(十三)视图绘制的几个方法

    三个可进行绘制的方法 在自定义视图中,有三个函数可以重写用于界面绘制,在视图创建过程中,三个函数的执行顺序依次是:onLayout.onDraw.dispatchDraw. 1.onLayout(bo ...

  2. Android开发笔记(序)写在前面的目录

    知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面希望通过分享自己的经验教训,与网友互相切磋,从而去芜存菁进一步提升自己的水平.因此博主就想,入门的东西咱就不写了,人不能老停留在入 ...

  3. Android开发笔记(序)

    本开发笔记,借鉴与其他开发者整理的文章范例与心得体会.在这里作为开发过程中的一个总结与笔记式记录. 如有侵犯作者权益,请及时联系告知删除.俗话说:集百家成一言,去粕成金. ************** ...

  4. Android开发笔记(序)写在前面的目录大全

    转自  湖前琴亭 的博客https://blog.csdn.net/aqi00/article/details/50012511 知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面 ...

  5. Andriod开发之二十:Android开发笔记(序)写在前面的目录

    https://blog.csdn.net/aqi00/article/details/50038385 知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面希望通过分享自己的经验教 ...

  6. Android开发笔记(九十九)圆形转盘

    圆形转盘的实现思想 圆形转盘的运用场景常见的有:抽奖转盘.圆形菜单列表.热点客户端环状列表等等.对于圆形转盘的编码实现,主要难点除了手势的触摸控制之外,就在于旋转角度的计算了.下面是旋转角度计算的解决 ...

  7. Android开发笔记(九十五)自定义Drawable

    Drawable Bitmap是Android对图像的定义描述,而Drawable则是对图像的展现描述,在View视图中显示图像都是通过Drawable来实现的.其中有关Bitmap的介绍参见< ...

  8. Android开发笔记(八十七)几个修饰关键字

    原生native native是方法修饰符,表示该方法是由其他一种语言(如C/C++)实现的原生方法.其实native只在JNI接口中使用,java代码中只有原生方法的定义,具体的实现代码在其他语言( ...

  9. Android开发笔记(八十六)几个特殊的类

    接口interface interface是一些功能的集合,但它只定义了对象必须实现的成员,而不包含成员的实现代码,成员的具体代码由实现接口的类提供.Android对接口的使用场景主要有三类:事件监听 ...

最新文章

  1. Java SE和Java EE应用的性能调优
  2. Science重磅!人类特有基因触发猴子长出更强大的大脑
  3. 部署SCCM2012之先决条件准备
  4. syslog数据接收并处理
  5. 查询正在运行的ORACLE进程
  6. idea部署maven+javaweb项目到jboss
  7. forms角色验证,以普通用户身份登陆管理页面先弹出警告信息窗口
  8. Java面向对象的程序设计
  9. php旧物交易开源代码_仿互站PHP源码 虚拟物品在线交易网站源码 附14套风格
  10. python科学计算库
  11. 如何将程序下载到单片机
  12. hough变换理解 原理 步骤
  13. USB Mass Storage大容量存储的基本知识
  14. 【制作】基于金沙滩51单片机的电子跑表
  15. AutoIt教程资源及autoit学习方法
  16. 局部加权回归Loess对比MFCC三角滤波(吴恩达机器学习中说,Loess算法用到了aircraft的自动驾驶中)
  17. 首次试水天池数据大赛——7个小时玩了把美年健康AI大赛
  18. ESP8266-WIFI模块使用AT指令连接外网服务器
  19. Eigen中四元数Quaterniond的初始
  20. 谷歌浏览器87版本 iframe_谷歌Chrome的“混合内容”更新将会影响电商网站,自建站卖家如何应对?...

热门文章

  1. Leetcode每日一题:面试题17.12 binode
  2. 花书+吴恩达深度学习(三)反向传播算法 Back Propagation
  3. GitHub Pages自定义域名如何支持https
  4. 为参加脱欧协议表决 英国工党女议员将延后剖腹产
  5. python 读取邮件内容_Python 如何提取邮件内容
  6. python中for语句的使用_对Python中for复合语句的使用示例讲解
  7. [Ext JS]3.2.2 文本输入框textfield
  8. 非对称加密原理及RSA加密步骤
  9. 使用C++ 调用 C# 程序
  10. 助力泵嗡嗡响解决方法_突破不可能,3D打印革命性的制造高效高扭矩的径向活塞泵...