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

Flutter技术问询:如何解析HTML文本适配RichText组件

Parsing HTML to RichText in Dart/Flutter

Great question! Converting basic HTML tags like <p>, <b>, <i> into TextSpan objects for Flutter's RichText is a common requirement. Let's break down two reliable approaches depending on your needs:

1. Manual Parsing (For Simple, Limited Tags)

If your HTML only contains a small set of tags (like the ones in your example), you can handle parsing manually with string manipulation. This works best for flat or lightly nested structures—complex nesting can get tricky, but it's quick for straightforward cases.

Here's a tailored example for your input:

import 'package:flutter/material.dart';

List<TextSpan> parseSimpleHtml(String html) {
  // Process nested <i> tags first to preserve their style inside <b>
  final processedHtml = html.replaceAll(RegExp(r'<i>(.*?)</i>'), r'|italic|$1|/italic|');
  
  // Split the content into bold and non-bold segments
  final parts = processedHtml.split(RegExp(r'<b>(.*?)</b>'));
  final spans = <TextSpan>[];

  for (int i = 0; i < parts.length; i++) {
    if (i % 2 == 0) {
      // Non-bold text, handle paragraph breaks
      final text = parts[i].replaceAll(RegExp(r'<p>|</p>'), '').trim();
      if (text.isNotEmpty) spans.add(TextSpan(text: '$text\n\n'));
    } else {
      // Bold text, split out italic segments
      final boldParts = parts[i].split(RegExp(r'\|italic\|(.*?)\|/italic\|'));
      for (int j = 0; j < boldParts.length; j++) {
        if (j % 2 == 0) {
          spans.add(TextSpan(
            text: boldParts[j],
            style: const TextStyle(fontWeight: FontWeight.bold),
          ));
        } else {
          spans.add(TextSpan(
            text: boldParts[j],
            style: const TextStyle(
              fontWeight: FontWeight.bold,
              fontStyle: FontStyle.italic,
            ),
          ));
        }
      }
    }
  }

  return spans;
}

Use it in RichText like this:

RichText(
  text: TextSpan(
    style: DefaultTextStyle.of(context).style,
    children: parseSimpleHtml('<p> hello <b> im bold and <i> im bold and italic </i> bold only continues.. </b> </p>'),
  ),
)

2. Use the html Package (Robust, Scalable)

For a more reliable solution—especially if you expect nested tags or might add more HTML elements later—use the official html package to parse the HTML into a DOM tree, then recursively convert nodes to TextSpan. This is the approach I'd recommend for most real-world cases.

Step 1: Add the dependency

Add this to your pubspec.yaml:

dependencies:
  html: ^0.15.4 # Use the latest version available

Step 2: Parse HTML to TextSpans

Create a helper function to traverse the DOM nodes:

import 'package:flutter/material.dart';
import 'package:html/parser.dart' show parse;
import 'package:html/dom.dart' as dom;

List<TextSpan> parseHtmlToTextSpans(String html) {
  final document = parse(html);
  return _traverseNodes(document.body!.nodes);
}

List<TextSpan> _traverseNodes(List<dom.Node> nodes) {
  final spans = <TextSpan>[];

  for (final node in nodes) {
    if (node is dom.Text) {
      // Handle plain text nodes
      spans.add(TextSpan(text: node.text));
    } else if (node is dom.Element) {
      TextStyle currentStyle = const TextStyle();

      // Apply styles based on the HTML tag
      switch (node.localName) {
        case 'b':
          currentStyle = currentStyle.copyWith(fontWeight: FontWeight.bold);
          break;
        case 'i':
          currentStyle = currentStyle.copyWith(fontStyle: FontStyle.italic);
          break;
        case 'p':
          // Add line breaks for paragraphs and process children
          spans.addAll(_traverseNodes(node.nodes));
          spans.add(const TextSpan(text: '\n\n'));
          continue; // Skip wrapping <p> in a style span
      }

      // Recursively process child nodes, inheriting the current style
      final childSpans = _traverseNodes(node.nodes);
      spans.add(TextSpan(style: currentStyle, children: childSpans));
    }
  }

  return spans;
}

Step 3: Use in RichText

RichText(
  text: TextSpan(
    style: DefaultTextStyle.of(context).style, // Inherit app's default text style
    children: parseHtmlToTextSpans('<p> hello <b> im bold and <i> im bold and italic </i> bold only continues.. </b> </p>'),
  ),
)

This approach is easy to extend—if you need to handle tags like <u> (underline) or <strong>, just add another case to the switch statement.


内容的提问来源于stack exchange,提问作者krishnakumarcn

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 12:58:13