Android T9搜索

作者: 一息尚存 | 来源:发表于2016-10-13 20:57 被阅读1290次

    在android中实现一个通过T9搜索联系人的功能。

    使用的库: https://github.com/YiiGuxing/T9Search

    引用:

    compile 'cn.tinkling.t9:t9search:1.1.0'
    

    生成匹配串:

    String t9Key = T9Utils.buildT9Key("重新称重", new PinyinProvider() {
        @Override
        public String[] getPinyin(char input) {
            // 在这里生成拼音,如果需要支持多音字匹配,返回多个拼音就行了。
            // 由于多音字的拼音可能只是声调不同,去除声调后是一样的(如:“啊”字),所以建议做一下去重复操作。
            return new String[]{/*拼音...*/};
        }
    });
    // 匹配串用于搜索匹配
    

    搜索匹配:

    String t9Key; // 上面生成的匹配串
    String constraint; // 输入的搜索键
    // 开始匹配并返回匹配信息
    T9MatchInfo matchInfo = T9Matcher.matches(t9Key, constraint);
    // ...
    

    以上便是基本的用法。

    一个简单封装的工具类:(通过 pinyin4j 库实现汉字转拼音)

    • T9SearchSupport.java
    import android.support.annotation.NonNull;
    import android.support.v4.util.Pools;
    import android.text.Spannable;
    import android.text.SpannableStringBuilder;
    import android.text.TextUtils;
    import android.text.style.ForegroundColorSpan;
    
    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;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Set;
    
    import cn.tinkling.t9.PinyinProvider;
    import cn.tinkling.t9.T9MatchInfo;
    import cn.tinkling.t9.T9Matcher;
    import cn.tinkling.t9.T9Utils;
    
    public final class T9SearchSupport {
    
        private static final PinyinProvider PINYIN_PROVIDER;
        private static final HanyuPinyinOutputFormat FORMAT;
    
        private static final Pools.SynchronizedPool<Set<String>> SET_POOL;
    
        static {
            FORMAT = new HanyuPinyinOutputFormat();
            FORMAT.setCaseType(HanyuPinyinCaseType.UPPERCASE);
            FORMAT.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
            FORMAT.setVCharType(HanyuPinyinVCharType.WITH_V);
    
            SET_POOL = new Pools.SynchronizedPool<>(4);
    
            PINYIN_PROVIDER = new PinyinProvider() {
                @Override
                public String[] getPinyin(char input) {
                    Set<String> set = SET_POOL.acquire();
                    if (set == null) {
                        set = new HashSet<>();
                    }
    
                    try {
                        String[] pys = PinyinHelper.toHanyuPinyinStringArray(input, FORMAT);
                        if (pys == null)
                            return null;
    
                        // 去除重复
                        set.addAll(Arrays.asList(pys));
                        return set.toArray(new String[set.size()]);
                    } catch (BadHanyuPinyinOutputFormatCombination e) {
                        e.printStackTrace();
                    } finally {
                        set.clear();
                        SET_POOL.release(set);
                    }
    
                    return null;
                }
            };
        }
    
        private T9SearchSupport() {
        }
    
        /**
         * 生成T9键
         *
         * @param input 输入
         * @return T9键
         */
        @NonNull
        public static String buildT9Key(String input) {
            return T9Utils.buildT9Key(input, PINYIN_PROVIDER);
        }
    
        /**
         * 过虑
         */
        public static List<Contact> filter(List<Contact> contacts, String key) {
            ArrayList<Contact> filtered = new ArrayList<>();
    
            if (contacts != null && contacts.size() > 0) {
                for (Contact contact : contacts) {
                    T9MatchInfo nameMatch = T9Matcher.matches(contact.t9Key, key);
                    T9MatchInfo numberMatch = T9Matcher.matchesNumber(contact.phoneNumber, key);
    
                    if (nameMatch.found() || numberMatch.found()) {
                        Contact c = new Contact(contact);
                        c.nameMatchInfo = nameMatch;
                        c.phoneNumberMatchInfo = numberMatch;
                        filtered.add(c);
                    }
                }
    
                Collections.sort(filtered, COMPARATOR);
            }
    
            return filtered;
        }
    
        /**
         * 高亮文本
         */
        public static SpannableStringBuilder highLight(SpannableStringBuilder buffer,
                                                       T9MatchInfo matchInfo,
                                                       String text,
                                                       int color) {
            buffer.clear();
            if (!TextUtils.isEmpty(text)) {
                buffer.append(text);
    
                final int maxLength = text.length();
                while (matchInfo != null) {
                    int start = matchInfo.start();
                    int end = start + matchInfo.length();
                    if ((matchInfo.found() && start < maxLength && end <= maxLength)) {
                        buffer.setSpan(new ForegroundColorSpan(color), start, end,
                                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                    }
    
                    matchInfo = matchInfo.next();
                }
            }
    
            return buffer;
        }
    
        private static final Comparator<Contact> COMPARATOR = new Comparator<Contact>() {
    
            @Override
            public int compare(Contact left, Contact right) {
                T9MatchInfo leftNameMatch = left.nameMatchInfo;
                T9MatchInfo rightNameMatch = right.nameMatchInfo;
                if (leftNameMatch.found()) {
                    if (rightNameMatch.found()) {
                        int lStart = leftNameMatch.start();
                        int rStart = rightNameMatch.start();
    
                        if (lStart < rStart) {
                            return -1;
                        } else if (lStart > rStart) {
                            return 1;
                        }
    
                        int lLen = getMatchLength(leftNameMatch);
                        int rLen = getMatchLength(rightNameMatch);
    
                        int temp = left.name.length() - lLen - (right.name.length() - rLen);
                        if (temp != 0) {
                            if (lLen < rLen) {
                                return 1;
                            } else if (lLen > rLen) {
                                return -1;
                            }
                            return temp;
                        } else if (lLen != rLen) {
                            if (left.name.length() > right.name.length()) {
                                return 1;
                            } else if (left.name.length() < right.name.length()) {
                                return -1;
                            }
                        }
    
                        return left.name.compareToIgnoreCase(right.name);
    
                    } else {
                        return -1;
                    }
                } else if (rightNameMatch.found()) {
                    return 1;
                }
    
                T9MatchInfo leftNumberMatch = left.phoneNumberMatchInfo;
                T9MatchInfo rightNumberMatch = right.phoneNumberMatchInfo;
                if (leftNumberMatch.found()) {
                    if (rightNumberMatch.found()) {
                        int lStart = leftNumberMatch.start();
                        int rStart = rightNumberMatch.start();
    
                        if (lStart < rStart) {
                            return -1;
                        } else if (lStart > rStart) {
                            return 1;
                        } else {
                            return left.phoneNumber.compareToIgnoreCase(right.phoneNumber);
                        }
                    } else {
                        return -1;
                    }
                } else if (rightNumberMatch.found()) {
                    return 1;
                }
    
                return 0;
            }
    
            private int getMatchLength(T9MatchInfo matchInfo) {
                int len = 0;
                while (matchInfo != null) {
                    len += matchInfo.length();
                    matchInfo = matchInfo.next();
                }
    
                return len;
            }
        };
    }
    
    • Contact.java
    import cn.tinkling.t9.T9MatchInfo;
    
    public class Contact {
    
        public String name;
        public String phoneNumber;
        public String t9Key;
        public T9MatchInfo nameMatchInfo;
        public T9MatchInfo phoneNumberMatchInfo;
    
        public Contact(String name, String phoneNumber, String t9Key) {
            this.name = name;
            this.phoneNumber = phoneNumber;
            this.t9Key = t9Key;
        }
    
        public Contact(Contact contact) {
            this(contact.name, contact.phoneNumber, contact.t9Key);
        }
    }
    

    预览:

    预览预览

    相关文章

      网友评论

        本文标题:Android T9搜索

        本文链接:https://www.haomeiwen.com/subject/qwxgyttx.html