Flutter文本样式处理求助:带<ins>标签的文本样式定制方案
解决方案
方法一:自定义字符串解析 + RichText
这种方式无需依赖第三方包,完全自主控制解析逻辑,适合需求明确且不想引入额外依赖的场景。
实现步骤:
- 预处理字符串:先把原字符串中的转义标签替换为可直接识别的标记,比如将
<code><ins></code>替换为<ins>,<code></ins></code>替换为</ins>,方便后续拆分文本区块。 - 拆分文本区块:按
<ins>和</ins>将原字符串拆分为「标签外前缀」、「标签内内容」、「标签外后缀」三个部分。 - 解析每个区块的文本样式:针对每个区块,用正则匹配
@xxx和#xxx标签,分别生成对应的TextSpan,再按区块设置对应样式:- 标签外:普通文本为黑色,@/#标签为黑色加粗
- 标签内:普通文本为红色,@/#标签为红色加粗
代码示例:
import 'package:flutter/material.dart'; class StyledTextWidget extends StatelessWidget { final String originalText = "@123 #123 text normal <code><ins></code>\n@tag #hashtag text normal <code></ins></code>"; StyledTextWidget({super.key}); @override Widget build(BuildContext context) { // 预处理字符串,替换转义标签 String processedText = originalText .replaceAll('<code><ins></code>', '<ins>') .replaceAll('<code></ins></code>', '</ins>'); // 拆分区块 List<String> parts = processedText.split(RegExp(r'<ins>|</ins>')); String outsidePrefix = parts[0]; String insideContent = parts.length > 1 ? parts[1] : ''; String outsideSuffix = parts.length > 2 ? parts[2] : ''; // 生成TextSpan列表 List<TextSpan> spans = []; // 添加标签外前缀 spans.addAll(_parseTextPart(outsidePrefix, isInsideIns: false)); // 添加标签内内容 if (insideContent.isNotEmpty) { spans.addAll(_parseTextPart(insideContent, isInsideIns: true)); } // 添加标签外后缀 spans.addAll(_parseTextPart(outsideSuffix, isInsideIns: false)); return RichText(text: TextSpan(children: spans)); } List<TextSpan> _parseTextPart(String text, {required bool isInsideIns}) { // 匹配@标签、#话题和普通文本的正则 RegExp regExp = RegExp(r'(@\w+|#\w+|[\s\S]+?(?=@|#|$))'); Iterable<Match> matches = regExp.allMatches(text); return matches.map((match) { String content = match.group(0)!; TextStyle style; if (content.startsWith('@') || content.startsWith('#')) { // @或#标签:加粗,颜色根据区块设置 style = TextStyle( fontWeight: FontWeight.bold, color: isInsideIns ? Colors.red : Colors.black, ); } else { // 普通文本:颜色根据区块设置 style = TextStyle( color: isInsideIns ? Colors.red : Colors.black, ); } return TextSpan(text: content, style: style); }).toList(); } }
方法二:使用第三方包 styled_text
如果不想自己编写解析逻辑,可以用styled_text包,它支持自定义标签和正则匹配样式,能快速实现需求。
实现步骤:
- 添加依赖:在
pubspec.yaml中添加styled_text: ^[最新版本](可直接用pub上的最新版本号) - 配置StyledText组件:
- 自定义
<ins>标签,设置内部文本的默认样式为红色 - 用
patterns匹配@xxx和#xxx,分别设置对应的加粗样式(内部为红色加粗,外部为黑色加粗)
- 自定义
代码示例:
import 'package:flutter/material.dart'; import 'package:styled_text/styled_text.dart'; class StyledTextWithPackage extends StatelessWidget { final String originalText = "@123 #123 text normal <code><ins></code>\n@tag #hashtag text normal <code></ins></code>"; StyledTextWithPackage({super.key}); @override Widget build(BuildContext context) { String processedText = originalText .replaceAll('<code><ins></code>', '<ins>') .replaceAll('<code></ins></code>', '</ins>'); return StyledText( text: processedText, tags: { 'ins': StyledTextTag( style: const TextStyle(color: Colors.red), // 内部的@和#标签设置红色加粗 patterns: [ StyledTextPattern( r'@\w+', style: const TextStyle( fontWeight: FontWeight.bold, color: Colors.red, ), ), StyledTextPattern( r'#\w+', style: const TextStyle( fontWeight: FontWeight.bold, color: Colors.red, ), ), ], ), }, patterns: [ // 外部的@和#标签设置黑色加粗 StyledTextPattern( r'@\w+', style: const TextStyle( fontWeight: FontWeight.bold, color: Colors.black, ), ), StyledTextPattern( r'#\w+', style: const TextStyle( fontWeight: FontWeight.bold, color: Colors.black, ), ), ], style: const TextStyle(color: Colors.black), ); } }
注意事项
- 预处理字符串时要确保转义标签替换正确,避免拆分区块出错
- 正则表达式可根据实际需求调整,比如如果@或#后面允许包含特殊字符,需要修改正则的匹配规则
- 使用第三方包时,注意查看包的官方文档,确保版本兼容当前Flutter版本
内容的提问来源于stack exchange,提问作者Mr Robin
相关产品推荐
相关产品推荐

