【问题标题】:How to highlight correct word on searchDelegate?如何在 searchDelegate 上突出显示正确的单词?
【发布时间】:2019-06-12 09:20:27
【问题描述】:

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

在我的 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))
          ])),

【问题讨论】:

  • 这个问题你看不懂吗?因为我添加了屏幕截图,您可以更好地理解。
  • 这里显示了一个 UI 问题。但是家庭作业的照片是没有意义的。例如,请参阅idownvotedbecau.se/imageofcode。此处任何 text 并且可以在问题中显示为(格式化)文本的内容都应该是文本。
  • 严肃地说:停止假设什么是合适的,什么不是。转到help center 并开始阅读。

标签: flutter dart


【解决方案1】:

我写了一个返回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;
}

基于您的代码的示例:

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

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

【讨论】:

  • 我可以从编辑中看出你已经明白了 :) 很高兴它有帮助!
  • 谢谢兄弟@George...一个问题:可以回答这个问题兄弟stackoverflow.com/q/56629955/9139407
  • 非常好。这对我有帮助
【解决方案2】:

根据@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;
}

用法和@George的回答一样:

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

【讨论】:

    【解决方案3】:

    很抱歉我回答得太晚了,但我也想对这种“问题”表示支持。

    我想找到一种不同的方法,我在不使用 if 语句的情况下找到了它,它看起来很漂亮,而且可能更容易管理它; 我认为“建议字符串”在 3 个子字符串的最坏情况下被划分:侧面有 2 个字符串,中间有一个。正如您所想象的那样,中间的那个是“粗体”的。而已! 如果没有对应关系,显然建议框中不会显示任何结果。 我直接复制并粘贴了我使用的相同代码。

    return ListView.builder(
            itemCount: _posts.length,
            itemBuilder: (context, index) {
              int startIndex = _posts[index].title.toLowerCase().indexOf(query.toLowerCase());
              return ListTile(
                title: query.isEmpty
                    ? Text(_posts[index].title)
                    : RichText(
                        text: TextSpan(
                        text: _posts[index].title.substring(0, startIndex),
                        style: TextStyle(color: Colors.grey),
                        children: [
                          TextSpan(
                            text: _posts[index]
                                .title
                                .substring(startIndex, startIndex + query.length),
                            style: TextStyle(
                                fontWeight: FontWeight.bold, color: Colors.black),
                          ),
                          TextSpan(
                            text: _posts[index]
                                .title
                                .substring(startIndex + query.length),
                            style: TextStyle(color: Colors.grey),
                          )
                        ],
                      )),
                subtitle: Text(_posts[index].date),
              );
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-03-21
      • 1970-01-01
      • 2014-08-07
      • 2011-02-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-19
      相关资源
      最近更新 更多