javascript
复制代码
import 'package:flutter/material.dart';
/// 富文本,高亮字符
class HighlightedText extends StatelessWidget {
final String text;
final List<String> keywords; //关键字
final Color highlightColor; //高亮颜色
final TextStyle normalStyle; //正常字体样式
final TextStyle highlightStyle; //高亮字体样式
final int? maxLines;
final TextOverflow overflow;
final TextAlign textAlign;
const HighlightedText({
super.key,
required this.text,
required this.keywords,
this.highlightColor = Colors.red,
this.normalStyle = const TextStyle(),
this.highlightStyle = const TextStyle(),
this.textAlign = TextAlign.start,
this.maxLines,
this.overflow = TextOverflow.ellipsis,
});
@override
Widget build(BuildContext context) {
/// 如果没有关键词,直接返回普通文本
if (keywords.isEmpty || text.isEmpty) {
return Text(text, style: normalStyle);
}
/// 过滤掉空关键词
final validKeywords = keywords.where((keyword) => keyword.isNotEmpty).toList();
if (validKeywords.isEmpty) {
return Text(text, style: normalStyle);
}
/// 创建正则表达式来匹配所有关键词(按长度降序排列,避免短关键词优先匹配)
validKeywords.sort((a, b) => b.length.compareTo(a.length));
final pattern = RegExp(
validKeywords.map((keyword) => RegExp.escape(keyword)).join('|'),
caseSensitive: false,
);
final matches = pattern.allMatches(text);
final spans = <TextSpan>[];
int lastEnd = 0;
/// 遍历所有匹配项
for (final match in matches) {
/// 添加匹配前的普通文本
if (match.start > lastEnd) {
spans.add(TextSpan(
text: text.substring(lastEnd, match.start),
style: normalStyle,
));
}
/// 获取匹配的文本
final matchedText = text.substring(match.start, match.end);
/// 添加高亮的关键词 - 修复样式合并问题
spans.add(TextSpan(
text: matchedText,
style: highlightStyle.merge(TextStyle(
color: highlightColor,
fontWeight: FontWeight.bold,
)),
));
lastEnd = match.end;
}
/// 添加剩余的普通文本
if (lastEnd < text.length) {
spans.add(TextSpan(
text: text.substring(lastEnd),
style: normalStyle,
));
}
/// 如果没有匹配到任何关键词,返回普通文本
if (spans.isEmpty) {
return Text(text, style: normalStyle);
}
return RichText(
maxLines: maxLines,
overflow: overflow,
textAlign: textAlign,
text: TextSpan(children: spans),
);
}
}