244 lines
6.2 KiB
Dart
244 lines
6.2 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
class KtTextHighlightUtils {
|
|
/// 高亮搜索结果(支持正则匹配)
|
|
static TextSpan highlightSearchResult({
|
|
required String text,
|
|
required String searchTerm,
|
|
TextStyle? normalStyle,
|
|
TextStyle? highlightStyle,
|
|
bool caseSensitive = false,
|
|
}) {
|
|
if (searchTerm.isEmpty ||
|
|
!text.toLowerCase().contains(searchTerm.toLowerCase())) {
|
|
return TextSpan(text: text, style: normalStyle);
|
|
}
|
|
|
|
final matches = RegExp(
|
|
searchTerm,
|
|
caseSensitive: caseSensitive,
|
|
).allMatches(text);
|
|
|
|
final List<TextSpan> children = [];
|
|
int lastEnd = 0;
|
|
|
|
for (final match in matches) {
|
|
// 添加匹配前的文本
|
|
if (match.start > lastEnd) {
|
|
children.add(
|
|
TextSpan(
|
|
text: text.substring(lastEnd, match.start),
|
|
style: normalStyle,
|
|
),
|
|
);
|
|
}
|
|
|
|
// 添加匹配的文本(高亮) - 修改为文本颜色区分
|
|
children.add(
|
|
TextSpan(
|
|
text: text.substring(match.start, match.end),
|
|
style:
|
|
highlightStyle ??
|
|
TextStyle(
|
|
color: Colors.blue, // 默认使用蓝色文本
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
);
|
|
|
|
lastEnd = match.end;
|
|
}
|
|
|
|
// 添加剩余的文本
|
|
if (lastEnd < text.length) {
|
|
children.add(TextSpan(text: text.substring(lastEnd), style: normalStyle));
|
|
}
|
|
|
|
return TextSpan(children: children);
|
|
}
|
|
|
|
/// 高亮文本(简单子字符串匹配)
|
|
static TextSpan highlightText({
|
|
required String text,
|
|
required String keyword,
|
|
Color highlightColor = Colors.blue, // 修改为文本颜色
|
|
Color textColor = Colors.black,
|
|
double fontSize = 16,
|
|
FontWeight normalWeight = FontWeight.normal,
|
|
FontWeight highlightWeight = FontWeight.bold,
|
|
bool caseSensitive = false,
|
|
String? fontFamily,
|
|
}) {
|
|
if (keyword.isEmpty) {
|
|
return TextSpan(
|
|
text: text,
|
|
style: TextStyle(
|
|
color: textColor,
|
|
fontSize: fontSize,
|
|
fontWeight: normalWeight,
|
|
),
|
|
);
|
|
}
|
|
|
|
final String searchText = caseSensitive ? text : text.toLowerCase();
|
|
final String searchKeyword = caseSensitive
|
|
? keyword
|
|
: keyword.toLowerCase();
|
|
|
|
if (!searchText.contains(searchKeyword)) {
|
|
return TextSpan(
|
|
text: text,
|
|
style: TextStyle(
|
|
color: textColor,
|
|
fontSize: fontSize,
|
|
fontWeight: normalWeight,
|
|
fontFamily: fontFamily,
|
|
),
|
|
);
|
|
}
|
|
|
|
final List<TextSpan> children = [];
|
|
int startIndex = 0;
|
|
|
|
while (startIndex < text.length) {
|
|
final int matchIndex = searchText.indexOf(searchKeyword, startIndex);
|
|
|
|
if (matchIndex == -1) {
|
|
// 剩余文本无匹配,全部添加
|
|
children.add(
|
|
TextSpan(
|
|
text: text.substring(startIndex),
|
|
style: TextStyle(
|
|
color: textColor,
|
|
fontSize: fontSize,
|
|
fontWeight: normalWeight,
|
|
fontFamily: fontFamily,
|
|
),
|
|
),
|
|
);
|
|
break;
|
|
}
|
|
|
|
// 添加匹配前的文本
|
|
if (matchIndex > startIndex) {
|
|
children.add(
|
|
TextSpan(
|
|
text: text.substring(startIndex, matchIndex),
|
|
style: TextStyle(
|
|
color: textColor,
|
|
fontSize: fontSize,
|
|
fontWeight: normalWeight,
|
|
fontFamily: fontFamily,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
// 添加匹配的文本(高亮) - 修改为文本颜色区分
|
|
children.add(
|
|
TextSpan(
|
|
text: text.substring(matchIndex, matchIndex + keyword.length),
|
|
style: TextStyle(
|
|
color: highlightColor, // 使用指定的高亮文本颜色
|
|
fontSize: fontSize,
|
|
fontWeight: highlightWeight,
|
|
fontFamily: fontFamily,
|
|
),
|
|
),
|
|
);
|
|
|
|
// 更新起始位置
|
|
startIndex = matchIndex + keyword.length;
|
|
}
|
|
|
|
return TextSpan(children: children);
|
|
}
|
|
|
|
/// 高亮多个关键词
|
|
static TextSpan highlightMultipleKeywords({
|
|
required String text,
|
|
required List<String> keywords,
|
|
Color highlightColor = Colors.blue, // 修改为文本颜色
|
|
Color textColor = Colors.black,
|
|
double fontSize = 16,
|
|
String? fontFamily,
|
|
}) {
|
|
if (keywords.isEmpty || text.isEmpty) {
|
|
return TextSpan(
|
|
text: text,
|
|
style: TextStyle(
|
|
color: textColor,
|
|
fontSize: fontSize,
|
|
fontFamily: fontFamily,
|
|
),
|
|
);
|
|
}
|
|
|
|
// 创建一个包含所有关键词的正则表达式
|
|
final regexPattern = keywords.map(RegExp.escape).join('|');
|
|
final regex = RegExp(regexPattern, caseSensitive: false);
|
|
|
|
final matches = regex.allMatches(text);
|
|
if (matches.isEmpty) {
|
|
return TextSpan(
|
|
text: text,
|
|
style: TextStyle(
|
|
color: textColor,
|
|
fontSize: fontSize,
|
|
fontFamily: fontFamily,
|
|
),
|
|
);
|
|
}
|
|
|
|
final List<TextSpan> children = [];
|
|
int lastEnd = 0;
|
|
|
|
for (final match in matches) {
|
|
// 添加匹配前的文本
|
|
if (match.start > lastEnd) {
|
|
children.add(
|
|
TextSpan(
|
|
text: text.substring(lastEnd, match.start),
|
|
style: TextStyle(
|
|
color: textColor,
|
|
fontSize: fontSize,
|
|
fontFamily: fontFamily,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
// 添加匹配的文本(高亮) - 修改为文本颜色区分
|
|
children.add(
|
|
TextSpan(
|
|
text: text.substring(match.start, match.end),
|
|
style: TextStyle(
|
|
color: highlightColor, // 使用指定的高亮文本颜色
|
|
fontSize: fontSize,
|
|
fontWeight: FontWeight.bold,
|
|
fontFamily: fontFamily,
|
|
),
|
|
),
|
|
);
|
|
|
|
lastEnd = match.end;
|
|
}
|
|
|
|
// 添加剩余的文本
|
|
if (lastEnd < text.length) {
|
|
children.add(
|
|
TextSpan(
|
|
text: text.substring(lastEnd),
|
|
style: TextStyle(
|
|
color: textColor,
|
|
fontSize: fontSize,
|
|
fontFamily: fontFamily,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
return TextSpan(children: children);
|
|
}
|
|
}
|