欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

android仿微信通讯录搜索示例(匹配拼音,字母,索引位置)

程序员文章站 2023-12-19 20:51:34
前言: 仿微信通讯录搜索功能,通过汉字或拼音首字母找到匹配的联系人并显示匹配的位置 一:先看效果图 字母索引 搜索匹配 二:功能分析 1:汉字转...

前言:

仿微信通讯录搜索功能,通过汉字或拼音首字母找到匹配的联系人并显示匹配的位置

一:先看效果图

android仿微信通讯录搜索示例(匹配拼音,字母,索引位置)

字母索引

android仿微信通讯录搜索示例(匹配拼音,字母,索引位置)

搜索匹配

二:功能分析

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

上一篇:

下一篇: