You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter文本样式处理求助:带<ins>标签的文本样式定制方案

解决方案

方法一:自定义字符串解析 + RichText

这种方式无需依赖第三方包,完全自主控制解析逻辑,适合需求明确且不想引入额外依赖的场景。

实现步骤:

  1. 预处理字符串:先把原字符串中的转义标签替换为可直接识别的标记,比如将<code>&lt;ins&gt;</code>替换为<ins>,<code>&lt;/ins&gt;</code>替换为</ins>,方便后续拆分文本区块。
  2. 拆分文本区块:按<ins>和</ins>将原字符串拆分为「标签外前缀」、「标签内内容」、「标签外后缀」三个部分。
  3. 解析每个区块的文本样式:针对每个区块,用正则匹配@xxx和#xxx标签,分别生成对应的TextSpan,再按区块设置对应样式:
    • 标签外:普通文本为黑色,@/#标签为黑色加粗
    • 标签内:普通文本为红色,@/#标签为红色加粗

代码示例:

import 'package:flutter/material.dart';

class StyledTextWidget extends StatelessWidget {
  final String originalText = "@123 #123 text normal <code>&lt;ins&gt;</code>\n@tag #hashtag text normal  <code>&lt;/ins&gt;</code>";

  StyledTextWidget({super.key});

  @override
  Widget build(BuildContext context) {
    // 预处理字符串,替换转义标签
    String processedText = originalText
        .replaceAll('<code>&lt;ins&gt;</code>', '<ins>')
        .replaceAll('<code>&lt;/ins&gt;</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包,它支持自定义标签和正则匹配样式,能快速实现需求。

实现步骤:

  1. 添加依赖:在pubspec.yaml中添加styled_text: ^[最新版本](可直接用pub上的最新版本号)
  2. 配置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>&lt;ins&gt;</code>\n@tag #hashtag text normal  <code>&lt;/ins&gt;</code>";

  StyledTextWithPackage({super.key});

  @override
  Widget build(BuildContext context) {
    String processedText = originalText
        .replaceAll('<code>&lt;ins&gt;</code>', '<ins>')
        .replaceAll('<code>&lt;/ins&gt;</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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 16:14:55