zoukankan      html  css  js  c++  java
  • android开发之使用拼音搜索汉字

    国庆回了趟家,昨天真不想走,离家近的感觉太好。唉,不扯这些,说说今天的正事吧。
    上篇博客中介绍了自定义AutoCompleteTextView ,但是用到了一个很蹩脚的技术,就是我们事先把每个汉字的拼音当作一个字段输入进去了,在实际的开发中肯定不会这样做,我们要通过代码自动生成汉字的拼音,就像我们的手机通讯录,比如我们要查找“张三”这个人,我们只需要输入“zs”、“cs”或者“zhangsan”、“changsan”就能搜索到该人,那么我们该怎么来实现这样的功能呢?

    本文所述案例是在上篇博客的基础上实现的,如果还没阅读上篇博客,请看android开发之自定义AutoCompleteTextView
    本文要实现的整体效果如下图所示:
    这里写图片描述


    在上篇博客中我们自定义了AutoCompleteTextView的Adapter,本文中,我们继续对这个Adapter进行深化改造。

    主要改造两个地方,第一个地方是在构造方法中初始化拼音集合:

    改造后的构造方法:

        public MyActAdapter(Context context, List<Book> books, int maxMatch) {
            this.books = books;
            this.context = context;
            this.maxMatch = maxMatch;
            initPinYinList();
        }

    这个方法主要是初始化两个List集合,一个是pinYinList 另一个是pinYinAllList ,前者是所有书的作者姓名拼音的首字母集合,后者是所有书的作者姓名拼音全拼集合。

        private void initPinYinList() {
            pinYinList = new ArrayList<Set<String>>();
            pinYinAllList = new ArrayList<Set<String>>();
            PinYin4j pinyin = new PinYin4j();
            for (int i = 0; i < books.size(); i++) {
                pinYinList.add(pinyin.getPinyin(books.get(i).getAuthor().toString()));
                pinYinAllList.add(pinyin.getAllPinyin(books.get(i).getAuthor().toString()));
            }
        }

    这里还涉及到两个类,如下:

    PinYin4j.java

    package com.example.myact;
    
    import java.util.Arrays;  
    import java.util.HashSet;  
    import java.util.Set;  
    
    public class PinYin4j {  
    
    
        public PinYin4j(){  
        }  
        /** 
         * 字符串集合转换字符串(逗号分隔) 
         *  
         * @author wangsong 
         * @param stringSet 
         * @return 
         */  
        public 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();  
        }  
    
    
        /** 
         * 获取汉字拼音全拼
         *  
         * @author wangsong 
         * @param src 
         * @return Set<String> 
         */  
        public Set<String> getAllPinyin(String src) {  
            char[] srcChar;  
            srcChar = src.toCharArray();  
            String[][] temp = new String[src.length()][];  
            for (int i = 0; i < srcChar.length; i++) {  
                char c = srcChar[i];  
                if (String.valueOf(c).matches("[\u4E00-\u9FA5]+")) {  
                    String[] t = PinyinHelper.getUnformattedHanyuPinyinStringArray(c);  
                    temp[i] = new String[t.length];  
                    for(int j=0;j<t.length;j++){  
                        temp[i][j]=t[j].replaceAll("\d", "");//获取全拼  
                    }  
                } else if (((int) c >= 65 && (int) c <= 90)  
                        || ((int) c >= 97 && (int) c <= 122)||c>=48&&c<=57||c==42) {
                    temp[i] = new String[] { String.valueOf(srcChar[i]) };  
                } else {  
                    temp[i] = new String[] {"null!"};  
                }  
    
            }  
            String[] pingyinArray = paiLie(temp);  
            return array2Set(pingyinArray);
        }  
        /** 
         * 获取汉字拼音首字母集合
         *  
         * @author wangsong 
         * @param src 
         * @return Set<String> 
         */  
        public Set<String> getPinyin(String src) {  
                char[] srcChar;  
                srcChar = src.toCharArray();  
                String[][] temp = new String[src.length()][];  
                for (int i = 0; i < srcChar.length; i++) {  
                    char c = srcChar[i];  
                    if (String.valueOf(c).matches("[\u4E00-\u9FA5]+")) {  
                            String[] t = PinyinHelper.getUnformattedHanyuPinyinStringArray(c);  
                            temp[i] = new String[t.length];  
                            for(int j=0;j<t.length;j++){  
                                temp[i][j]=t[j].substring(0,1);
                            }  
                    } else if (((int) c >= 65 && (int) c <= 90)  
                            || ((int) c >= 97 && (int) c <= 122)||c>=48&&c<=57||c==42) {
                        temp[i] = new String[] { String.valueOf(srcChar[i]) };  
                    } else {  
                        temp[i] = new String[] {"null!"};  
                    }  
    
                }  
                String[] pingyinArray = paiLie(temp);  
                return array2Set(pingyinArray);
        }  
    
        /* 
         * 求2维数组所有排列组合情况 
         * 比如:{{1,2},{3},{4},{5,6}}共有2中排列,为:1345,1346,2345,2346 
         */  
        private String[] paiLie(String[][] str){  
            int max=1;  
            for(int i=0;i<str.length;i++){  
                max*=str[i].length;  
            }  
            String[] result=new String[max];  
            for(int i = 0; i < max; i++){  
                    String s = "";  
                    int temp = 1;      //注意这个temp的用法。  
                    for(int j = 0; j < str.length; j++){  
                        temp *= str[j].length;  
                        s += str[j][i / (max / temp) % str[j].length];  
                    }  
                    result[i]=s;  
            }  
    
            return result;  
        }  
          /**
           * 去掉重复项  
           * @param tArray
           * @return
           */
        public static <T extends Object> Set<T> array2Set(T[] tArray) {     
            Set<T> tSet = new HashSet<T>(Arrays.asList(tArray));     
            // TODO 没有一步到位的方法,根据具体的作用,选择合适的Set的子类来转换。     
            return tSet;     
        }   
    }  

    PinyinHelper.java

    package com.example.myact;
    
    import java.io.BufferedInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.util.Properties;
    
    public class PinyinHelper {
        private static PinyinHelper instance;
        private Properties properties = null;
    
        public static String[] getUnformattedHanyuPinyinStringArray(char ch) {
            return getInstance().getHanyuPinyinStringArray(ch);
        }
    
        private PinyinHelper() {
            initResource();
        }
    
        public static PinyinHelper getInstance() {
            if (instance == null) {
                instance = new PinyinHelper();
            }
            return instance;
        }
    
        private void initResource() {
            try {
                final String resourceName = "/assets/unicode_to_hanyu_pinyin.txt";
                // final String resourceName = "/assets/unicode_py.ini";
    
                properties = new Properties();
                properties.load(getResourceInputStream(resourceName));
    
            } catch (FileNotFoundException ex) {
                ex.printStackTrace();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    
        private BufferedInputStream getResourceInputStream(String resourceName) {
            return new BufferedInputStream(
                    PinyinHelper.class.getResourceAsStream(resourceName));
        }
    
        private String[] getHanyuPinyinStringArray(char ch) {
            String pinyinRecord = getHanyuPinyinRecordFromChar(ch);
    
            if (null != pinyinRecord) {
                int indexOfLeftBracket = pinyinRecord.indexOf(Field.LEFT_BRACKET);
                int indexOfRightBracket = pinyinRecord
                        .lastIndexOf(Field.RIGHT_BRACKET);
    
                String stripedString = pinyinRecord.substring(indexOfLeftBracket
                        + Field.LEFT_BRACKET.length(), indexOfRightBracket);
    
                return stripedString.split(Field.COMMA);
    
            } else
                return null;
    
        }
    
        private String getHanyuPinyinRecordFromChar(char ch) {
            int codePointOfChar = ch;
            String codepointHexStr = Integer.toHexString(codePointOfChar)
                    .toUpperCase();
            String foundRecord = properties.getProperty(codepointHexStr);
            return foundRecord;
        }
    
        class Field {
            static final String LEFT_BRACKET = "(";
            static final String RIGHT_BRACKET = ")";
            static final String COMMA = ",";
        }
    
        public static String[] toHanyuPinyinStringArray(char ch) {
            return getUnformattedHanyuPinyinStringArray(ch);
        }
    }

    这里是初始化拼音集合。
    第二个改造的地方就是在过滤器中增加过滤的条件。

    这是最新的过滤器,和上文相比,这里只是增加了一个else分支,在else分支中判断搜索条件是否符合要求。

        private class ArrayFilter extends Filter {
    
            @Override
            protected FilterResults performFiltering(CharSequence constraint) {
                FilterResults results = new FilterResults();
                if (mFilterBooks == null) {
                    mFilterBooks = new ArrayList<Book>(books);
                }
                // 如果没有过滤条件则不过滤
                if (constraint == null || constraint.length() == 0) {
                    results.values = mFilterBooks;
                    results.count = mFilterBooks.size();
                } else {
                    List<Book> retList = new ArrayList<Book>();
                    // 过滤条件
                    String str = constraint.toString().toLowerCase();
                    Book book;
                    // 循环变量数据源,如果有属性满足过滤条件,则添加到result中
                    for (int i = 0; i < mFilterBooks.size(); i++) {
                        book = mFilterBooks.get(i);
                        if (book.getAuthor().contains(str)
                                || book.getName().contains(str)
                                || (book.getId() + "").contains(str)
                                || (book.getPrice() + "").contains(str)
                                || book.getPinyin().contains(str)) {
                            retList.add(book);
                        } else {
                            //查看作者姓名拼音首字母是否符合过滤条件
                            Set<String> pinyinSet = pinYinList.get(i);
                            Iterator<String> pinyin = pinyinSet.iterator();
                            while (pinyin.hasNext()) {
                                if (pinyin.next().toString().contains(str)) {
                                    retList.add(book);
                                    break;
                                }
                            }
                            //查看作者姓名拼音全拼是否符合过滤条件
                            Set<String> pinyinAllSet = pinYinAllList.get(i);
                            Iterator<String> pinyinAll = pinyinAllSet.iterator();
                            while (pinyinAll.hasNext()) {
                                if (pinyinAll.next().toString().contains(str)) {
                                    retList.add(book);
                                    break;
                                }
                            }
                        }
                        // if (maxMatch > 0) {
                        // if (retList.size() > maxMatch - 1) {
                        // break;
                        // }
                        // }
                    }
                    results.values = retList;
                    results.count = retList.size();
                }
                return results;
            }
    
            // 在这里返回过滤结果
            @Override
            protected void publishResults(CharSequence constraint,
                    FilterResults results) {
                // notifyDataSetInvalidated(),会重绘控件(还原到初始状态)
                // notifyDataSetChanged(),重绘当前可见区域
                books = (List<Book>) results.values;
                if (results.count > 0) {
                    notifyDataSetChanged();
                } else {
                    notifyDataSetInvalidated();
                }
            }
    
        }

    其实还是很简单的,有问题欢迎留言讨论。

    完整代码下载点这里。

    版权声明:本文为博主原创文章,未经博主允许不得转载。若有错误地方,还望批评指正,不胜感激。

  • 相关阅读:
    Web 组件是什么
    amazeui学习笔记二(进阶开发2)--Web组件简介Web Component
    .less为后缀的文件是什么
    amazeui学习笔记二(进阶开发1)--项目结构structure
    html中的瀑布流是什么
    HTML5 API 是什么
    epoll使用具体解释(精髓)
    DataTable.AcceptChanges方法有何用处
    cer, pfx 创建,而且读取公钥/密钥,加解密 (C#程序实现)
    超赞的.NET办公软件库
  • 原文地址:https://www.cnblogs.com/lenve/p/4889318.html
Copyright © 2011-2022 走看看