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;
    }
    1. setToneType 设置音标的显示方式:

      • HanyuPinyinToneType.WITH_TONE_MARK:在拼音字母上显示音标,如“zhòng”
      • HanyuPinyinToneType.WITH_TONE_NUMBER:在拼音字符串后面通过数字显示,如“zhong4”
      • HanyuPinyinToneType.WITHOUT_TONE:不显示音标
    2. setCaseType 设置拼音大小写:

      • HanyuPinyinCaseType.LOWERCASE:返回的拼音为小写字母
      • HanyuPinyinCaseType.UPPERCASE:返回的拼音为大写字母
    3. 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

转载于:https://www.cnblogs.com/qiangge-python/p/9685216.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值