py4j汉语转拼音多音字处理
先看下效果



一 、布局
<!-- 上面的搜索框 -->
<com.example.editablealphalist.widgget.ClearEditText
android:id="@+id/filter_edit"
android:layout_marginTop="5dip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/search_bar_edit_selector"
android:drawableLeft="@drawable/search_bar_icon_normal"
android:hint="请输入关键字"
android:singleLine="true"
android:textSize="15sp" /> <FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent" > <ListView
android:id="@+id/name_listview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:divider="@null" /> <!-- 中间显示的选中的大写首字母 -->
<TextView
android:id="@+id/dialog"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_gravity="center"
android:background="@drawable/show_head_toast_bg"
android:gravity="center"
android:textColor="@color/font_color_selected"
android:textSize="30sp"
android:visibility="gone" /> <!-- 右侧供选择的列表 -->
<com.example.editablealphalist.widgget.SideBar
android:id="@+id/sidrbar"
android:layout_width="30dp"
android:layout_height="match_parent"
android:layout_gravity="right|center" />
</FrameLayout>
二、自定义控件
2.1 ClearEditText 带删除按钮的输入框
public class ClearEditText extends AppCompatEditText implements OnFocusChangeListener, TextWatcher {
/**
* 删除按钮的引用
*/
private Drawable mClearDrawable;
public ClearEditText(Context context) {
this(context, null);
}
public ClearEditText(Context context, AttributeSet attrs) {
// 这里构造方法也很重要,不加这个很多属性不能再XML里面定义
this(context, attrs, android.R.attr.editTextStyle);
}
public ClearEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
// 获取EditText的DrawableRight,假如没有设置我们就使用默认的图片
mClearDrawable = getCompoundDrawables()[2];
if (mClearDrawable == null) {
mClearDrawable = getResources().getDrawable(R.drawable.emotionstore_progresscancelbtn);
}
mClearDrawable.setBounds(0, 0, mClearDrawable.getIntrinsicWidth(), mClearDrawable.getIntrinsicHeight());
setClearIconVisible(false);
setOnFocusChangeListener(this);
addTextChangedListener(this);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (getCompoundDrawables()[2] != null) {
if (event.getAction() == MotionEvent.ACTION_UP) {
boolean touchable = event.getX() > (getWidth() - getPaddingRight() - mClearDrawable.getIntrinsicWidth())
&& (event.getX() < ((getWidth() - getPaddingRight())));
if (touchable) { //选中了“删除”按钮
this.setText("");
}
}
}
return super.onTouchEvent(event);
}
/**
* 当ClearEditText焦点发生变化的时候,判断里面字符串长度设置清除图标的显示与隐藏
*/
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
setClearIconVisible(getText().length() > 0);
} else {
setClearIconVisible(false);
}
}
/**
* 设置清除图标的显示与隐藏,调用setCompoundDrawables为EditText绘制上去
*
* @param visible
*/
protected void setClearIconVisible(boolean visible) {
Drawable right = visible ? mClearDrawable : null;
setCompoundDrawables(getCompoundDrawables()[0], getCompoundDrawables()[1], right, getCompoundDrawables()[3]);
}
/**
* 当输入框里面内容发生变化的时候回调的方法
*/
@Override
public void onTextChanged(CharSequence s, int start, int count, int after) {
setClearIconVisible(s.length() > 0);
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void afterTextChanged(Editable s) {
}
}
2.2 SideBar 右侧首字母列表
/**
* 右侧首字母列表bar
* @author Jack
* @version 创建时间:2014-2-6 下午3:37:33
*/
public class SideBar extends View { /** 触摸事件 */
private OnTouchingLetterChangedListener onTouchingLetterChangedListener;
/** 26个字母 */
public static String[] characters = { "A", "B", "C", "D", "E", "F", "G",
"H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
"U", "V", "W", "X", "Y", "Z", "#" };
private int ifSelected = -1; // 选中
private Paint paint = new Paint();
private TextView mTextDialog; public void setTextView(TextView mTextDialog) {
this.mTextDialog = mTextDialog;
} public SideBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
} public SideBar(Context context, AttributeSet attrs) {
super(context, attrs);
} public SideBar(Context context) {
super(context);
} /**
* 重写这个方法
*/
protected void onDraw(Canvas canvas) { super.onDraw(canvas);
// 获取焦点改变背景颜色.
int height = getHeight(); // 获取对应高度
int width = getWidth(); // 获取对应宽度
int singleHeight = height / characters.length; // 获取每一个字母的高度 for (int i = 0; i < characters.length; i++) { // 设置颜色
paint.setColor(Color.rgb(33, 65, 98));
// 设置字体
paint.setTypeface(Typeface.DEFAULT_BOLD);
// 设置抗锯齿
paint.setAntiAlias(true);
// 设置字体大小
paint.setTextSize(20);
// 选中的状态
if (i == ifSelected) { paint.setColor(Color.parseColor("#3399ff"));
paint.setFakeBoldText(true);
}
// x坐标等于中间-字符串宽度的一半.
float xPos = width / 2 - paint.measureText(characters[i]) / 2;
float yPos = singleHeight * i + singleHeight;
canvas.drawText(characters[i], xPos, yPos, paint);
paint.reset();// 重置画笔
}
} @Override
public boolean dispatchTouchEvent(MotionEvent event) { final int action = event.getAction();
final float y = event.getY();// 点击y坐标
final int oldSelected = ifSelected;
final OnTouchingLetterChangedListener listener = onTouchingLetterChangedListener;
final int selected = (int) (y / getHeight() * characters.length);// 点击y坐标所占总高度的比例*b数组的长度就等于点击b中的个数. switch (action) { case MotionEvent.ACTION_UP: setBackgroundDrawable(new ColorDrawable(0x00000000));
ifSelected = -1;//
invalidate();
if (mTextDialog != null) {
mTextDialog.setVisibility(View.INVISIBLE);
}
break;
default: setBackgroundResource(R.drawable.sidebar_background);
if (oldSelected != selected) {
if (selected >= 0 && selected < characters.length) {
if (listener != null) {
listener.onTouchingLetterChanged(characters[selected]);
}
if (mTextDialog != null) {
mTextDialog.setText(characters[selected]);
mTextDialog.setVisibility(View.VISIBLE);
}
ifSelected = selected;
invalidate();
}
}
break;
}
return true;
} /**
* 向外公开的方法
* @param onTouchingLetterChangedListener
*/
public void setOnTouchingLetterChangedListener(OnTouchingLetterChangedListener onTouchingLetterChangedListener) { this.onTouchingLetterChangedListener = onTouchingLetterChangedListener;
} /**
* 触碰右侧列表时的回调接口
*/
public interface OnTouchingLetterChangedListener {
public void onTouchingLetterChanged(String s);
}
三、事件处理
3.1 右侧字母栏滑动处理
sideBar = (SideBar) findViewById(R.id.sidrbar);
dialog = (TextView) findViewById(R.id.dialog);
sideBar.setTextView(dialog);
// 设置右侧触摸监听
sideBar.setOnTouchingLetterChangedListener(new SideBar.OnTouchingLetterChangedListener() { @Override
public void onTouchingLetterChanged(String s) {
// 该字母首次出现的位置
int position = adapter.getPositionForSection(s.charAt(0));
if (position != -1) {
sortListView.setSelection(position);
}
}
});
3.2 输入框事件处理
//查询框设置监听
mClearEditText = (ClearEditText) findViewById(R.id.filter_edit);
// 根据输入框输入值的改变来过滤搜索
mClearEditText.addTextChangedListener(new TextWatcher() { @Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
// 当输入框里面的值为空,更新为原来的列表,否则为过滤数据列表
filterData(s.toString());
} @Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) { } @Override
public void afterTextChanged(Editable s) {
}
});
/**
* 根据输入框中的值来过滤数据源,截取含有查询字符串的数据
*
* @param filterStr 查询字符串
*/
private void filterData(String filterStr) { List<SortModel> filterDataList = new ArrayList<SortModel>();
if (TextUtils.isEmpty(filterStr)) { filterDataList = sourceDataList;
} else { filterDataList.clear();
for (SortModel sortModel : sourceDataList) { String name = sortModel.getName();
/*if (name.indexOf(filterStr.toString()) != -1 || characterParser.getSelling(name).startsWith(filterStr.toString())) { filterDataList.add(sortModel);
}*/
if (name.indexOf(filterStr.toString()) != -1 || pinyin4JUtil.convertChineseToPinyin(name).startsWith(filterStr.toString())) { filterDataList.add(sortModel);
}
}
}
// 根据a-z进行排序
Collections.sort(filterDataList, pinyinComparator);
adapter.updateListView(filterDataList);
}
四、汉字转拼音及多音字处理
4.1 初始化转换格式
/**
* 获取拼音初始汉语拼音格式化实例
*
* @param withTone
* @return
*/
private HanyuPinyinOutputFormat getHanyuPinyinOutputFormat(boolean withTone) {
HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
if (withTone) {
//直接用音标符
format.setToneType(HanyuPinyinToneType.WITH_TONE_MARK);// WITHOUT_TONE:无音标 (xing)
//format.setToneType(HanyuPinyinToneType.WITH_TONE_NUMBER);// WITH_TONE_NUMBER:1-4数字表示英标 (xing2)
//直接用ü (nü)
format.setVCharType(HanyuPinyinVCharType.WITH_U_UNICODE);//WITH_V:用v表示ü (nv) //WITH_U_AND_COLON:用”u:”表示ü (nu:)
format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
} else {
//直接用音标符
format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
format.setVCharType(HanyuPinyinVCharType.WITH_U_UNICODE);
format.setCaseType(HanyuPinyinCaseType.UPPERCASE);
}
return format;
}
setToneType 设置音标的显示方式:
- HanyuPinyinToneType.WITH_TONE_MARK:在拼音字母上显示音标,如“zhòng”
- HanyuPinyinToneType.WITH_TONE_NUMBER:在拼音字符串后面通过数字显示,如“zhong4”
- HanyuPinyinToneType.WITHOUT_TONE:不显示音标
setCaseType 设置拼音大小写:
- HanyuPinyinCaseType.LOWERCASE:返回的拼音为小写字母
- HanyuPinyinCaseType.UPPERCASE:返回的拼音为大写字母
setVCharType 设置拼音字母“ü”的显示方式
汉语拼音中的“ü”不能简单的通过英文来表示,所以需要单独定义“ü”的显示格式- HanyuPinyinVCharType.WITH_U_UNICODE:默认的显示方式,输出“ü”
- HanyuPinyinVCharType.WITH_V:输出“v”
- HanyuPinyinVCharType.WITH_U_AND_COLON:输出“u:”
4.2 转换成汉语拼音
HanyuPinyinOutputFormat defaultFormat = getHanyuPinyinOutputFormat(false);
String[] results = PinyinHelper.toHanyuPinyinStringArray(ch, defaultFormat);//ch是要转化的汉字,用char表示。如'重'
如果results中拼音个数如果大于1说明该汉字是多音字
4.3 多音字处理
4.3.1 获取py4j.txt中的数据转换成map形式
private HashMap<String, String> initDictionary(Context context) {
String fileName = "py4j.txt";
InputStreamReader inputReader = null;
BufferedReader bufferedReader = null;
HashMap<String, String> polyphoneMap = new HashMap<String, String>();
try {
inputReader = new InputStreamReader(context.getResources().getAssets().open(fileName), "UTF-8");
bufferedReader = new BufferedReader(inputReader);
String line = null;
while ((line = bufferedReader.readLine()) != null) {
//Log.d(TAG,"======"+line);
if (line != null) {
String[] arr = line.split("#");
String pinyin = arr[0];
String chinese = arr[1];
if (chinese != null) {
String[] strs = chinese.split(" ");
List<String> list = Arrays.asList(strs);
pinyinMap.put(pinyin, list);
}
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
将py4j.txt保存到assets目录通过context.getResources().getAssets().open(fileName)打开,存放到字符流中。
4.3.2 判断多音字并找到最优的拼音
{
int len = results.length;
if (len == 1) { // 不是多音字
String[] pinyinArray = getHanyuStrings(true, ch);
pinyin.append(pinyinArray[0]);
} else if (results[0].equals(results[1])) { //非多音字 有多个音,取第一个
//pinyin.append(results[0]);
String[] pinyinArray = getHanyuStrings(true, ch);
pinyin.append(pinyinArray[0]);
} else { // 多音字
int length = chinese.length();
boolean flag = false;
String s = null;
List<String> keyList = null;
for (int x = 0; x < len; x++) {
String py = results[x];
keyList = pinyinMap.get(py.toLowerCase());
resultPos = x;
if (i + 3 <= length) { //后向匹配2个汉字 大西洋
s = chinese.substring(i, i + 3);
if (keyList != null && (keyList.contains(s))) {
flag = true;
break;
}
}
if (i + 2 <= length) { //后向匹配 1个汉字 大西
s = chinese.substring(i, i + 2);
if (keyList != null && (keyList.contains(s))) {
flag = true;
break;
}
}
if ((i - 2 >= 0) && (i + 1 <= length)) { // 前向匹配2个汉字 龙固大
s = chinese.substring(i - 2, i + 1);
if (keyList != null && (keyList.contains(s))) {
flag = true;
break;
}
}
if ((i - 1 >= 0) && (i + 1 <= length)) { // 前向匹配1个汉字 固大
s = chinese.substring(i - 1, i + 1);
if (keyList != null && (keyList.contains(s))) {
flag = true;
break;
}
}
if ((i - 1 >= 0) && (i + 2 <= length)) { //前向1个,后向1个 固大西
s = chinese.substring(i - 1, i + 2);
if (keyList != null && (keyList.contains(s))) {
flag = true;
break;
}
}
}
if (!flag) {//都没有找到,匹配默认的 读音 大
s = String.valueOf(ch);
for (int x = 0; x < len; x++) {
String py = results[x];
keyList = pinyinMap.get(py.toLowerCase());
if (keyList != null && (keyList.contains(s))) {
String[] pinyinArray = getHanyuStrings(true, ch);
pinyin.append(pinyinArray[x]);
break;
}
}
} else {
String[] pinyinArray = getHanyuStrings(true, ch);
pinyin.append(pinyinArray[resultPos]);
}
}
}
如果是多音字,则去匹配py4j.txt中的字符是否存在找到对应的多音字下标
String[] pinyinArray = getHanyuStrings(true, ch);
pinyin.append(pinyinArray[resultPos]);
...
private String[] getHanyuStrings(boolean withTone, char ch) {
HanyuPinyinOutputFormat format = getHanyuPinyinOutputFormat(withTone);
String[] pinyinArray = new String[0];
try {
pinyinArray = PinyinHelper.toHanyuPinyinStringArray(ch, format);
} catch (BadHanyuPinyinOutputFormatCombination badHanyuPinyinOutputFormatCombination) {
badHanyuPinyinOutputFormatCombination.printStackTrace();
}
return pinyinArray;
}

五、缺点
判断多音字存在缺陷,只能通过py4j.txt字库中查找,字库资源不完善。
https://github.com/MichealPan9999/chinesetopinyin
py4j汉语转拼音多音字处理的更多相关文章
- C# 汉语转拼音
汉语转拼音或首字母 通常不少网站上有汉语转拼音功能,今天就小记下这段汉语转拼音的代码,自己测试ok,现把代码贴出来,以备日后使用: 效果 用法很简单后台使用到了两个类文件,一个是:ConvertHzT ...
- java:工具(汉语转拼音,压缩包,EXCEL,JFrame窗口和文件选择器,SFTP上传下载,FTP工具类,SSH)
1.汉语转拼音: import net.sourceforge.pinyin4j.PinyinHelper; import net.sourceforge.pinyin4j.format.HanyuP ...
- java 汉语转拼音(全拼,首字母)
import java.util.*; import net.sourceforge.pinyin4j.PinyinHelper;import net.sourceforge.pinyin4j.for ...
- JS汉语转拼音脚本
测试代码: var anhui = "安徽"; //获得全拼 pinyin.getFullChars(anhui); //获得首拼 pinyin.getCamelChars(anh ...
- js汉语转拼音(全拼、首字母、拼音首字母)
新建js文件first_alphabet.js // JavaScript Document // 汉字拼音首字母列表 本列表包含了20902个汉字,用于配合 ToChineseSpell //函数使 ...
- 汉语转拼音pinyin4j
分享一个将汉语转成拼音的工具包:pinyin4j-2.5.0.jar,下载地址:http://download.csdn.net/detail/abc_key/7629141 使用例如以下代码 imp ...
- Java-汉字繁体拼音转换
import com.github.stuxuhai.jpinyin.ChineseHelper; import com.github.stuxuhai.jpinyin.PinyinFormat; i ...
- C#编写的通过汉字得到拼音和五笔码
public static class SpellAndWbConfig { #region 变量声明 // XML文件读取实例 /// <summary> /// XML文件读取实例 / ...
- .net 生成拼音码与五笔码
首先加入配置文件: <?xml version="1.0" encoding="utf-8" ?> <CodeConfig> <S ...
随机推荐
- python序列化
一. 序列化 1 定义: 在我们存储数据或者⽹网络传输数据的时候. 需要对我们的对象进⾏行行处理理. 把对象处理理成 ⽅方便便存储和传输的数据格式. 这个过程叫序列列化. 不同的序列列化, 结果也不同 ...
- python第三天,字符串续
字符串类型 在python中字符串类型可以用 成对单引号,如:'你好,中国.': 也可以用成对双引号,如:"厉害了,我滴国".代码如下: 通过.title(),可以将一段话的首字母 ...
- nodejs -Router
Node 用 request 事件来处理请求响应,事件内使用分支语句处理不同路径的请求,而 Express 封装了这些操作,使得代码简洁优雅 但如果请求路径变多,都写在 app.js 文件里的话,就会 ...
- 注解 java.lang.annotation.Inherited 介绍
在Spring Boot中大量使用了@Inherited注解.我们来了解一下这个注解的用法,注解的源码: package java.lang.annotation; /** * Indicates t ...
- delphi 的插件机制与自动更新
delphi 的插件机制与自动更新 : 1.https://download.csdn.net/download/cxp_2008/2226978 参考 2.https://download.cs ...
- MySQL之路 ——1、安装跳坑
最近几天准备写一个JavaWeb的简单登录,注册试下手:所谓”工欲善其事必先利其器“,然后数据库方面的话,考虑用MySQL.在安装MySQL过程中,碰到了一些问题(大同小异),记录在此,诸君共勉. 1 ...
- cocos开发插件笔记
写插件菜单时要注意大小写 { "name": "hello-world", "version": "0.0.1", &q ...
- svn更新出现冲突的解决方法
Conflict discovered in '/Users/apple/EtaxiAppServer/common/src/com/yaotaxi/db/MongoDBHelper.java'. S ...
- 003_ab http压测工具
一. ab -r -k -c 20000 -n 25000000 https://www.uuwatch.me/abtest #ab压测工具单机最大并发为20000,可以在多台机器上执行以增大并发 y ...
- hibernate映射(学生-科目-成绩)
实体类 1 public class Student { 2 private int id; 3 private String name; 4 private Set<Score> sco ...