如何在searchDelegate上突出显示正确的单词?

use*_*407 6 dart flutter

我突出显示了这个词,但不是正确的词。

在我的 BuilderSuggection 中,我添加了这样的代码,

检查我的搜索委托

 title: RichText(
          text: TextSpan(
              text: suggestList[index].d.substring(0, query.length),
              style: TextStyle(
                  color: Colors.black, fontWeight: FontWeight.bold),
              children: [
            TextSpan(
                text: suggestList[index].d.substring(query.length),
                style: TextStyle(color: Colors.grey))
          ])),
Run Code Online (Sandbox Code Playgroud)

Geo*_*rge 19

我写了一个快速函数,它返回一个列表TextSpan

函数将查询字符串与源字符串进行匹配,一一枚举匹配项,将源字符串切割成几部分:匹配之前、匹配之后和匹配本身 - 使其加粗。

它旨在用于RichText小部件。

List<TextSpan> highlightOccurrences(String source, String query) {
  if (query == null || query.isEmpty || !source.toLowerCase().contains(query.toLowerCase())) {
    return [ TextSpan(text: source) ];
  }
  final matches = query.toLowerCase().allMatches(source.toLowerCase());

  int lastMatchEnd = 0;

  final List<TextSpan> children = [];
  for (var i = 0; i < matches.length; i++) {
    final match = matches.elementAt(i);

    if (match.start != lastMatchEnd) {
      children.add(TextSpan(
        text: source.substring(lastMatchEnd, match.start),
      ));
    }

    children.add(TextSpan(
      text: source.substring(match.start, match.end),
      style: TextStyle(fontWeight: FontWeight.bold, color: Colors.black),
    ));

    if (i == matches.length - 1 && match.end != source.length) {
      children.add(TextSpan(
        text: source.substring(match.end, source.length),
      ));
    }

    lastMatchEnd = match.end;
  }
  return children;
}
Run Code Online (Sandbox Code Playgroud)

基于您的代码的示例:

RichText(
  text: TextSpan(
    children: highlightOccurrences(suggestList[index].d, query),
    style: TextStyle(color: Colors.grey),
  ),
),
Run Code Online (Sandbox Code Playgroud)

如果这有帮助,请告诉我。


Ika*_*ský 5

根据@George 的回答,有一个类似的函数,唯一的区别query是首先用空格分割,然后突出显示每个单独的单词。我花了一段时间才让它正常工作,所以为什么不分享:

List<TextSpan> highlightOccurrences(String source, String query) {
  if (query == null || query.isEmpty) {
    return [TextSpan(text: source)];
  }

  var matches = <Match>[];
  for (final token in query.trim().toLowerCase().split(' ')) {
    matches.addAll(token.allMatches(source.toLowerCase()));
  }

  if (matches.isEmpty) {
    return [TextSpan(text: source)];
  }
  matches.sort((a, b) => a.start.compareTo(b.start));

  int lastMatchEnd = 0;
  final List<TextSpan> children = [];
  for (final match in matches) {
    if (match.end <= lastMatchEnd) {
      // already matched -> ignore
    } else if (match.start <= lastMatchEnd) {
      children.add(TextSpan(
        text: source.substring(lastMatchEnd, match.end),
        style: TextStyle(fontWeight: FontWeight.bold, color: Colors.black),
      ));
    } else if (match.start > lastMatchEnd) {
      children.add(TextSpan(
        text: source.substring(lastMatchEnd, match.start),
      ));

      children.add(TextSpan(
        text: source.substring(match.start, match.end),
        style: TextStyle(fontWeight: FontWeight.bold, color: Colors.black),
      ));
    }

    if (lastMatchEnd < match.end) {
      lastMatchEnd = match.end;
    }
  }

  if (lastMatchEnd < source.length) {
    children.add(TextSpan(
      text: source.substring(lastMatchEnd, source.length),
    ));
  }

  return children;
}
Run Code Online (Sandbox Code Playgroud)

用法与@George 的回答相同:

RichText(
  text: TextSpan(
    children: highlightOccurrences(suggestList[index].d, query),
    style: TextStyle(color: Colors.grey),
  ),
),
Run Code Online (Sandbox Code Playgroud)