【问题标题】:Highlight searched text in ListView items突出显示 ListView 项中的搜索文本
【发布时间】:2014-05-28 07:14:47
【问题描述】:

我有一个ListView,我正在使用自定义适配器来显示数据。现在我想像上面的屏幕截图一样更改搜索到的文本字母颜色。

这是SearchView的代码

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.actionbar_menu_item, menu);
    SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
    final SearchView searchView = (SearchView) menu.findItem(R.id.action_search)
            .getActionView();
    searchView.setSearchableInfo(searchManager
            .getSearchableInfo(getComponentName()));
    searchView.setOnQueryTextListener(this);
        return super.onCreateOptionsMenu(menu);
        }

public boolean onQueryTextChange(String newText) {
    // this is adapter that will be filtered
      if (TextUtils.isEmpty(newText)){
            lvCustomList.clearTextFilter();
      }
      else{
            lvCustomList.setFilterText(newText.toString());
       }
    return false;
 }

@Override
public boolean onQueryTextSubmit(String query) {
    return false;
}

谢谢。

【问题讨论】:

  • Spannable String 是您的最佳选择。
  • @AdilSoomro 我想要粗体或改变颜色看起来像上面的屏幕截图(看上面)
  • Spannable String 也将涵盖这一点。
  • 我知道 Spannable String 被使用,但我不知道如何在我的情况下实现

标签: android string listview search


【解决方案1】:

我假设您有一个自定义适配器,实现了 getCount()getView() 并且已经过滤了项目,您只需要粗体部分。

为此,您需要使用SpannableString,它基本上是带有标记的文本。例如,TextAppearanceSpan 可用于更改字体、字体样式、大小和颜色。

因此,您应该更新适配器的 getView() 以将您使用 textView.setText() 的部分更改为或多或少像这样:

String filter = ...;
String itemValue = ...;

int startPos = itemValue.toLowerCase(Locale.US).indexOf(filter.toLowerCase(Locale.US));
int endPos = startPos + filter.length();

if (startPos != -1) // This should always be true, just a sanity check
{
    Spannable spannable = new SpannableString(itemValue);
    ColorStateList blueColor = new ColorStateList(new int[][] { new int[] {}}, new int[] { Color.BLUE });
    TextAppearanceSpan highlightSpan = new TextAppearanceSpan(null, Typeface.BOLD, -1, blueColor, null);

    spannable.setSpan(highlightSpan, startPos, endPos, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    textView.setText(spannable);
}
else
    textView.setText(itemValue);

【讨论】:

  • “filter.length()”对 endPos 有什么作用?
  • @AJW 它只是计算子字符串在较大字符串中的开始和结束位置。
  • 好的。那么,例如,可以突出显示较大字符串的一部分?另外,位置索引是从 0 开始还是从 1 开始?
【解决方案2】:

Android 搜索突出显示示例 [不区分大小写顺序]

1. 搜索: [突出显示特定单词]

public static SpannableStringBuilder highlightSearchText(SpannableStringBuilder fullText, String searchText) {

    if (searchText.length() == 0) return fullText;

    SpannableStringBuilder wordSpan = new SpannableStringBuilder(fullText);
    Pattern p = Pattern.compile(searchText, Pattern.CASE_INSENSITIVE);
    Matcher m = p.matcher(fullText);
    while (m.find()) {

        int wordStart = m.start();
        int wordEnd = m.end();

        setWordSpan(wordSpan, wordStart, wordEnd);

    }

    return wordSpan;
}

2. 搜索: [突出显示全文]

public static SpannableStringBuilder highlightSearchText(SpannableStringBuilder fullText, String searchText) {

    if (searchText.length() == 0) return fullText;

    final String searchBoundary = " \n()।.,;?-+!";
    char[] boundaries = searchBoundary.toCharArray();

    // highlight search text
    if (isNotEquals(searchText, boundaries)) {

        SpannableStringBuilder wordSpan = new SpannableStringBuilder(fullText);
        Pattern p = Pattern.compile(searchText, Pattern.CASE_INSENSITIVE);
        Matcher m = p.matcher(fullText);
        while (m.find()) {

            int wordStart = m.start();
            while (wordStart >= 0 && isNotEquals(fullText.charAt(wordStart), boundaries)) {
                --wordStart;
            }
            wordStart = wordStart + 1;

            int wordEnd = m.end();
            while (wordEnd < fullText.length() && isNotEquals(fullText.charAt(wordEnd), boundaries)) {
                ++wordEnd;
            }

            setWordSpan(wordSpan, wordStart, wordEnd);

        }

        return wordSpan;

    } else {
        return fullText;
    }
}

private static boolean isNotEquals(String searchText, char[] boundaries) {
    for (char boundary : boundaries) {
        boolean equals = searchText.equals(String.valueOf(boundary));
        if (equals) return false;
    }
    return true;
}

private static boolean isNotEquals(char charAt, char[] boundaries) {
    for (char boundary : boundaries) {
        boolean isEquals = charAt == boundary;
        if (isEquals) return false;
    }
    return true;
}

常用方法:

private static void setWordSpan(SpannableStringBuilder wordSpan, int wordStart, int wordEnd) {
    // Now highlight based on the word boundaries
    ColorStateList redColor = new ColorStateList(new int[][]{new int[]{}}, new int[]{0xffa10901});
    TextAppearanceSpan highlightSpan = new TextAppearanceSpan(null, Typeface.BOLD, -1, redColor, null);

    wordSpan.setSpan(highlightSpan, wordStart, wordEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    wordSpan.setSpan(new BackgroundColorSpan(0xFFFCFF48), wordStart, wordEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    wordSpan.setSpan(new RelativeSizeSpan(1.25f), wordStart, wordEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}

【讨论】:

  • 感谢您的分享!!它救了我一整天。
  • 我们为什么需要searchText = searchText.replace("'", "");
  • @HuyTTQ 如何调用 highlightSearchText ?我有一个类似的问题。你能帮我解决吗? stackoverflow.com/questions/60930395/…
【解决方案3】:

你可以使用CodeView库来实现这个功能,你只需要在适配器中创建2个变量来存储搜索结果的模式和突出显示的颜色,

private Pattern syntaxPattern;
private Color highlightColor = Color.MAGENTA;

并在适配器中为图案和颜色创建一个设置器

public void updateSyntaxPattern(Pattern pattern) {
    syntaxPattern = pattern;
    notifyDataSetChanged();
}

然后在 RecyclerAdapter 中的 ArrayAdapter 或 ViewHolder 的 getView 方法中,您需要将此模式添加到 CodeView 实例并删除旧模式(从上次搜索结果中)

if(syntaxPattern != null) {
    codeView.resetSyntaxPatternList();
    codeView.addSyntaxPattern(syntaxPattern, highlightColor);
}

现在在 SearchView onQueryTextSubmit 或 onQueryTextChange 中,取决于您希望荧光笔何时工作,您将选择其中之一,您需要从搜索结果中制作图案并将其设置到适配器

Pattern pattern = Pattern.compile(query);
adapter.updateSyntaxPattern(pattern);

它将完全按照您的意愿工作

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-07-24
    • 2012-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-25
    • 2017-12-11
    相关资源
    最近更新 更多