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 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 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 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 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); } }