我突出显示了该词,但未突出显示正确的词。
在我的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))
])),
答案 0 :(得分: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),
),
),
让我知道这是否有帮助。
答案 1 :(得分:1)
基于@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),
),
),
答案 2 :(得分:0)
很抱歉,我的回答很晚,但是我也想支持这种“问题”。
我想找到一种不同的方法,并且在不使用if语句的情况下找到了解决方法,这看起来很不错,甚至可能更易于管理。 我认为“建议字符串”在最坏的情况下分为3个子字符串:侧面2个字符串,中间1个字符串。您可以想象,中心的是“大胆”的一个。而已! 如果没有对应关系,则建议框中显然不会显示任何结果。 我直接复制并粘贴了我使用的相同代码。
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),
);