1. 程式人生 > >Android 實現漢字轉成拼音,實現ListView的A-Z字母排序,顯現多音字城市排序

Android 實現漢字轉成拼音,實現ListView的A-Z字母排序,顯現多音字城市排序

今天給大家帶來ListView的A-Z字母排序和過濾搜尋功能並且實現漢字轉成拼音的功能,我們知道一般我們對聯絡人,城市列表等實現A-Z的排序,因為聯絡人和城市列表我們可以直接從資料庫中獲取他的漢字拼音,而對於一般的資料,我們怎麼實現A-Z的排序,我們需要將漢字轉換成拼音就行了,接下來就帶大家實現一般資料的A-Z排序功能,首先先看下效果圖
在這裡插入圖片描述

=========================================================================

本人專案需求右邊索引字母只顯示列表有資料的對應的字母,多音字城市排序(重慶、長沙排在C字母下面),效果圖

在這裡插入圖片描述

================================================================================

上面是一個帶刪除按鈕的EditText,我們在輸入框中輸入可以自動過濾出我們想要的東西,當輸入框中沒有資料自動替換到原來的資料列表,然後下面一個ListView用來顯示資料列表,右側是一個字母索引表,當我們點選不同的字母,ListView會定位到該字母地方,瞭解了佈局之後,我們先看下專案結構吧
在這裡插入圖片描述

我按照專案中類的順序來一一介紹其功能

1.SortModel 一個實體類,裡面一個是ListView的name,另一個就是顯示的name拼音的首字母

package com.example.sortlistview;
 
public class SortModel {
 
	private String name;
//顯示的資料 private String sortLetters; //顯示資料拼音的首字母 public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSortLetters() { return sortLetters; } public void setSortLetters(String sortLetters) { this.sortLetters = sortLetters; }
}

2.SideBar類就是ListView右側的字母索引View,我們需要使用setTextView(TextView mTextDialog)來設定用來顯示當前按下的字母的TextView,以及使用setOnTouchingLetterChangedListener方法來設定回撥介面,在回撥方法onTouchingLetterChanged(String s)中來處理不同的操作

package com.example.sortlistview;
 
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.graphics.drawable.ColorDrawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;
 
public class SideBar extends View {
	// 觸控事件
    private OnTouchingLetterChangedListener onTouchingLetterChangedListener;
    // 26個字母
    public static String[] b = {"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 final int mNumber=26;//常規字母總數
    private int choose = -1;// 選中
    private Paint paint = new Paint();

    private TextView mTextDialog;

    private int textColor;
    private int textSize;
    private int textSelectorColor;

    private int mHeightPixels;

    public void setTextView(TextView mTextDialog) {
        this.mTextDialog = mTextDialog;
    }


    public SideBar(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        getWindowInfo(context);
        TypedArray a = context.obtainStyledAttributes(attrs,
                R.styleable.SideBar);
        textColor = a.getColor(R.styleable.SideBar_sbTextColor, Color.BLACK);
        textSize = a.getDimensionPixelSize(R.styleable.SideBar_sbTextSize, 24);
        textSelectorColor = a.getColor(R.styleable.SideBar_sbSelectedTextColor, Color.BLACK);
    }

    public SideBar(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
        getWindowInfo(context);
    }

    public SideBar(Context context) {
        super(context);
        getWindowInfo(context);
    }


    /**
     * 重寫這個方法
     */
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 獲取焦點改變背景顏色.
        int height = getHeight();// 獲取對應高度
        int width = getWidth(); // 獲取對應寬度
        //int singleHeight = height / b.length;// 獲取每一個字母的高度
        int singleHeight = height / mNumber;// 獲取每一個字母的高度

        for (int i = 0; i < b.length; i++) {
            paint.setColor(textColor);
            // paint.setColor(Color.WHITE);
            paint.setTypeface(Typeface.DEFAULT_BOLD);
            paint.setAntiAlias(true);
            paint.setTextSize(textSize);
            // 選中的狀態
            if (i == choose) {
                paint.setColor(textSelectorColor);
                paint.setFakeBoldText(true);
            }
            // x座標等於中間-字串寬度的一半.
            float xPos = width / 2 - paint.measureText(b[i]) / 2;
            //float yPos = singleHeight * i + singleHeight;
            //(整個高度/2-字母的高度*字母的數量/2)+字母的高度*第幾個+字母高度
            float yPos = (height/2-singleHeight*b.length/2)+singleHeight * i + singleHeight;//繪製相對於y座標的中間
            canvas.drawText(b[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 oldChoose = choose;
        final OnTouchingLetterChangedListener listener = onTouchingLetterChangedListener;
//        final int c = (int) (y / getHeight() * b.length);// 點選y座標所佔總高度的比例*b陣列的長度就等於點選b中的個數.
        int height = getHeight();// 獲取對應高度
        int singleHeight = height / mNumber;// 獲取每一個字母的高度
        //                      整個螢幕畫素的一半  字母集合對應的畫素高度的一半
        final int c = (int) ((y-mHeightPixels/2 + (mHeightPixels/mNumber*b.length/2)) / (singleHeight*b.length) * b.length);// 點選y座標所佔總高度的比例*b陣列的長度就等於點選b中的個數.

        switch (action) {
            case MotionEvent.ACTION_UP:
                setBackgroundDrawable(new ColorDrawable(0x00000000));
                choose = -1;//
                invalidate();
                if (mTextDialog != null) {
                    mTextDialog.setVisibility(View.INVISIBLE);
                }
                break;

            default:
                setBackgroundResource(R.drawable.sidebar_background);
                if (oldChoose != c) {
                    if (c >= 0 && c < b.length) {
                        if (listener != null) {
                            listener.onTouchingLetterChanged(b[c]);
                        }
                        if (mTextDialog != null) {
                            mTextDialog.setText(b[c]);
                            mTextDialog.setVisibility(View.VISIBLE);
                        }

                        choose = c;
                        invalidate();
                    }
                }

                break;
        }
        return true;
    }

    /**
     * 向外公開的方法
     *
     * @param onTouchingLetterChangedListener
     */
    public void setOnTouchingLetterChangedListener(
            OnTouchingLetterChangedListener onTouchingLetterChangedListener) {
        this.onTouchingLetterChangedListener = onTouchingLetterChangedListener;
    }

    /**
     * 介面
     *
     * @author coder
     */
    public interface OnTouchingLetterChangedListener {
        public void onTouchingLetterChanged(String s);
    }

    /**
     * 設定有資料對應的字母索引,並重繪
     * @param b
     */
    public void setLetter(String[] b){
        this.b=b;
        requestLayout();
        invalidate();
    }

    /**
     * 獲取裝置的螢幕資訊
     *
     * @return
     */
    private void getWindowInfo(Context context) {
        // DisplayMetrics類用於螢幕的描述資訊
        DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
        // 獲取螢幕畫素高度 px
        int height = displayMetrics.heightPixels;
        //獲取狀態列高度
        int result = 0;
        int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            result = context.getResources().getDimensionPixelSize(resourceId);
        }
        mHeightPixels=height-result-dip2px(context,48);//控制元件的高度=螢幕高度-狀態列高度-導航欄高度
    }

    /**
     * 根據手機的解析度從 dp 的單位 轉成為 px(畫素)
     */
    private static int dip2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }
 
}


3.CharacterParser 這個類是將漢字轉換成拼音的類,該拼音沒有聲調的,該類是單例類,其中定義了三個方法,在這個demo中用到的是getSelling(String chs)方法,將片語轉換成拼音

package com.example.sortlistview;
 
/**
 * Java漢字轉換為拼音
 * 
 */
public class CharacterParser {
	private static int[] pyvalue = new int[] {-20319, -20317, -20304, -20295, -20292, -20283, -20265, -20257, -20242, -20230, -20051, -20036, -20032,
			-20026, -20002, -19990, -19986, -19982, -19976, -19805, -19784, -19775, -19774, -19763, -19756, -19751, -19746, -19741, -19739, -19728,
			-19725, -19715, -19540, -19531, -19525, -19515, -19500, -19484, -19479, -19467, -19289, -19288, -19281, -19275, -19270, -19263, -19261,
			-19249, -19243, -19242, -19238, -19235, -19227, -19224, -19218, -19212, -19038, -19023, -19018, -19006, -19003, -18996, -18977, -18961,
			-18952, -18783, -18774, -18773, -18763, -18756, -18741, -18735, -18731, -18722, -18710, -18697, -18696, -18526, -18518, -18501, -18490,
			-18478, -18463, -18448, -18447, -18446, -18239, -18237, -18231, -18220, -18211, -18201, -18184, -18183, -18181, -18012, -17997, -17988,
			-17970, -17964, -17961, -17950, -17947, -17931, -17928, -17922, -17759, -17752, -17733, -17730, -17721, -17703, -17701, -17697, -17692,
			-17683, -17676, -17496, -17487, -17482, -17468, -17454, -17433, -17427, -17417, -17202, -17185, -16983, -16970, -16942, -16915, -16733,
			-16708, -16706, -16689, -16664, -16657, -16647, -16474, -16470, -16465, -16459, -16452, -16448, -16433, -16429, -16427, -16423, -16419,
			-16412, -16407, -16403, -16401, -16393, -16220, -16216, -16212, -16205, -16202, -16187, -16180, -16171, -16169, -16158, -16155, -15959,
			-15958, -15944, -15933, -15920, -15915, -15903, -15889, -15878, -15707, -15701, -15681, -15667, -15661, -15659, -15652, -15640, -15631,
			-15625, -15454, -15448, -15436, -15435, -15419, -15416, -15408, -15394, -15385, -15377, -15375, -15369, -15363, -15362, -15183, -15180,
			-15165, -15158, -15153, -15150, -15149, -15144, -15143, -15141, -15140, -15139, -15128, -15121, -15119, -15117, -15110,