android仿微信通讯录搜索示例(匹配拼音,字母,索引位置)
程序员文章站
2023-12-19 20:51:34
前言:
仿微信通讯录搜索功能,通过汉字或拼音首字母找到匹配的联系人并显示匹配的位置
一:先看效果图
字母索引
搜索匹配
二:功能分析
1:汉字转...
前言:
仿微信通讯录搜索功能,通过汉字或拼音首字母找到匹配的联系人并显示匹配的位置
一:先看效果图
字母索引
搜索匹配
二:功能分析
1:汉字转拼音
通讯录汉字转拼音(首个字符当考虑姓氏多音字), 现在转换拼音常见的有pinyin4j和tinypinyin, pinyin4j的功能强大,包含声调多音字,tinypinyin执行快占用内存少, 如果只是简单匹配通讯录,建议使用tinypinyin,用法也很简单这里不详细介绍
拼音类
public class cnpinyin <t extends cn> implements serializable, comparable<cnpinyin<t>> { /** * 对应首字首拼音字母 */ char firstchar; /** * 所有字符中的拼音首字母 */ string firstchars; /** * 对应的所有字母拼音 */ string[] pinyins; /** * 拼音总长度 */ int pinyinstotallength; public final t data; cnpinyin(t data) { this.data = data; } public char getfirstchar() { return firstchar; } @override public string tostring() { stringbuilder sb = new stringbuilder().append("--firstchar--").append(firstchar).append("--pinyins:"); for (string str : pinyins) { sb.append(str); } return sb.tostring(); } int comparevalue() { if (firstchar == def_char) { return 'z' + 1; } return firstchar; } @override public int compareto(cnpinyin<t> tcnpinyin) { int compare = comparevalue() - tcnpinyin.comparevalue(); if (compare == 0) { string chinese1 = data.chinese(); string chinese2 = tcnpinyin.data.chinese(); return chinese1.compareto(chinese2); } return compare; } }
2:定义索引栏 a~z,#控件
itemdecoration配合recyclerview实现stickyheader效果,此效果很常见不详细介绍
3:根据转换好的拼音快速匹配
搜索匹配才是核心, 以下匹配原则,有优先顺序如果有匹配成功不执行后面的匹配原则
a:匹配原字符 并找出所匹配的起始位置与结束位置,如有中文匹配将不执行后面的拼音匹配原则
static cnpinyinindex matcherchinese(cnpinyin cnpinyin, string keyword) { if (keyword.length() < cnpinyin.data.chinese().length()) { matcher matcher = pattern.compile(keyword, pattern.case_insensitive).matcher(cnpinyin.data.chinese()); if (matcher.find()) { return new cnpinyinindex(cnpinyin, matcher.start(), matcher.end()); } } return null; }
b:匹配单个字符拼音的首个字母(例如"游小陈"可以匹配y, x, c, yx, xc, yxc)
static cnpinyinindex matcherfirst(cnpinyin cnpinyin, string keyword) { if (keyword.length() <= cnpinyin.pinyins.length) { matcher matcher = pattern.compile(keyword, pattern.case_insensitive).matcher(cnpinyin.firstchars); if (matcher.find()) { return new cnpinyinindex(cnpinyin, matcher.start(), matcher.end()); } } return null; }
c:所有字符拼音的匹配, 且第一个匹配位置的拼音必须一致(例如"游小陈 youxiaochen", 必须匹配yo, you, xi, xia, xiao, ch, che, chen开头等 例如 yo youx, youxi, youxiao, xiaoc, xiaoch, xiaochen等等)
/** * 所有拼音匹配 * @param cnpinyin * @param keyword * @return */ static cnpinyinindex matcherspinyins(cnpinyin cnpinyin, string keyword) { if (keyword.length() > cnpinyin.pinyinstotallength) return null; int start = -1; int end = -1; for (int i = 0; i < cnpinyin.pinyins.length; i++) { string pat = cnpinyin.pinyins[i]; if (pat.length() >= keyword.length()) {//首个位置索引 matcher matcher = pattern.compile(keyword, pattern.case_insensitive).matcher(pat); if (matcher.find() && matcher.start() == 0) { start = i; end = i + 1; break; } } else { matcher matcher = pattern.compile(pat, pattern.case_insensitive).matcher(keyword); if (matcher.find() && matcher.start() == 0) {//全拼匹配第一个必须在0位置 start = i; string left = matcher.replacefirst(""); end = end(cnpinyin.pinyins, left, ++i); break; } } } if (start >= 0 && end >= start) { return new cnpinyinindex(cnpinyin, start, end); } return null; } /** * 根据匹配字符递归查找下一结束位置 * @param pinyingroup * @param pattern * @param index * @return -1 匹配失败 */ private static int end(string[] pinyingroup, string pattern, int index) { if (index < pinyingroup.length) { string pinyin = pinyingroup[index]; if (pinyin.length() >= pattern.length()) {//首个位置索引 matcher matcher = pattern.compile(pattern, pattern.case_insensitive).matcher(pinyin); if (matcher.find() && matcher.start() == 0) { return index + 1; } } else { matcher matcher = pattern.compile(pinyin, pattern.case_insensitive).matcher(pattern); if (matcher.find() && matcher.start() == 0) {//全拼匹配第一个必须在0位置 string left = matcher.replacefirst(""); return end(pinyingroup, left, index + 1); } } } return -1; }
最后附上源码https://github.com/youxiaochen/contactlist
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。