android仿微信通訊錄搜索示例(匹配拼音,字母,索引位置)
前言:
仿微信通訊錄搜索功能,通過漢字或拼音首字母找到匹配的聯(lián)系人并顯示匹配的位置
一:先看效果圖
字母索引
搜索匹配
二:功能分析
1:漢字轉(zhuǎn)拼音
通訊錄漢字轉(zhuǎn)拼音(首個(gè)字符當(dāng)考慮姓氏多音字), 現(xiàn)在轉(zhuǎn)換拼音常見的有pinyin4j和tinypinyin, pinyin4j的功能強(qiáng)大,包含聲調(diào)多音字,tinypinyin執(zhí)行快占用內(nèi)存少, 如果只是簡(jiǎn)單匹配通訊錄,建議使用tinypinyin,用法也很簡(jiǎn)單這里不詳細(xì)介紹
拼音類
public class CNPinyin <T extends CN> implements Serializable, Comparable<CNPinyin<T>> { /** * 對(duì)應(yīng)首字首拼音字母 */ char firstChar; /** * 所有字符中的拼音首字母 */ String firstChars; /** * 對(duì)應(yīng)的所有字母拼音 */ String[] pinyins; /** * 拼音總長(zhǎng)度 */ 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實(shí)現(xiàn)StickyHeader效果,此效果很常見不詳細(xì)介紹
3:根據(jù)轉(zhuǎn)換好的拼音快速匹配
搜索匹配才是核心, 以下匹配原則,有優(yōu)先順序如果有匹配成功不執(zhí)行后面的匹配原則
a:匹配原字符 并找出所匹配的起始位置與結(jié)束位置,如有中文匹配將不執(zhí)行后面的拼音匹配原則
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:匹配單個(gè)字符拼音的首個(gè)字母(例如"游小陳"可以匹配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:所有字符拼音的匹配, 且第一個(gè)匹配位置的拼音必須一致(例如"游小陳 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()) {//首個(gè)位置索引 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) {//全拼匹配第一個(gè)必須在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; } /** * 根據(jù)匹配字符遞歸查找下一結(jié)束位置 * @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()) {//首個(gè)位置索引 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) {//全拼匹配第一個(gè)必須在0位置 String left = matcher.replaceFirst(""); return end(pinyinGroup, left, index + 1); } } } return -1; }
最后附上源碼https://github.com/youxiaochen/ContactList
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 使用adb命令向Android模擬器中導(dǎo)入通訊錄聯(lián)系人的方法
- Android獲取手機(jī)通訊錄、sim卡聯(lián)系人及調(diào)用撥號(hào)界面方法
- Android通訊錄開發(fā)之刪除功能的實(shí)現(xiàn)方法
- Android個(gè)人手機(jī)通訊錄開發(fā)詳解
- Android實(shí)現(xiàn)通訊錄效果——獲取手機(jī)號(hào)碼和姓名
- Android讀取手機(jī)通訊錄聯(lián)系人到自己項(xiàng)目
- Android破解微信獲取聊天記錄和通訊錄信息(靜態(tài)方式)
- Android自定義View實(shí)現(xiàn)通訊錄字母索引(仿微信通訊錄)
- Android實(shí)現(xiàn)仿通訊錄側(cè)邊欄滑動(dòng)SiderBar效果代碼
- Android Studio實(shí)現(xiàn)簡(jiǎn)單的通訊錄
相關(guān)文章
Android BottomNavigationView與Fragment重建與重疊問題解決方法探索
這篇文章主要介紹了Android BottomNavigationView與Fragment重建與重疊問題解決,總的來說這并不是一道難題,那為什么要拿出這道題介紹?拿出這道題真正想要傳達(dá)的是解題的思路,以及不斷優(yōu)化探尋最優(yōu)解的過程。希望通過這道題能給你帶來一種解題優(yōu)化的思路2023-01-01A07_TimePicker & DatePicker & AnalogClock & Digi
本文將帶領(lǐng)大家一起學(xué)習(xí)時(shí)間日期和時(shí)鐘的設(shè)置。A07_TimePicker & DatePicker & AnalogClock & DigitalClock 的設(shè)置,感興趣的朋友可以參考下哈2013-06-06Android編程實(shí)現(xiàn)顯示在標(biāo)題上的進(jìn)度條功能【附源碼下載】
這篇文章主要介紹了Android編程實(shí)現(xiàn)顯示在標(biāo)題上的進(jìn)度條功能,涉及Android界面布局及相關(guān)組件屬性設(shè)置技巧,并附帶完整實(shí)例源碼供讀者下載參考,需要的朋友可以參考下2018-01-01詳解Android USB轉(zhuǎn)串口通信開發(fā)基本流程
本篇文章主要介紹了Android USB轉(zhuǎn)串口通信開發(fā)基本流程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04Android組件間通信--深入理解Intent與IntentFilter
本篇文章是對(duì)Android組件間通信Intent與IntentFilter進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05