Flutter HTML内容渲染插件flutter_widget_from_html_core_nic的使用

发布于 1周前 作者 yibo5220 来自 Flutter

Flutter HTML内容渲染插件flutter_widget_from_html_core_nic的使用

Flutter codecov Pub

Flutter包用于将HTML渲染为小部件,重点关注正确性和可扩展性。支持超过70种最流行的标签。

直观演示

Live demo Live demo

开始使用

在您的应用程序的pubspec.yaml文件中添加以下依赖:

dependencies:
  flutter_widget_from_html_core: ^0.10.5

使用方法

首先导入该包:

import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart';

然后在适当的地方使用HtmlWidget

HtmlWidget(
  // 必须参数(html)
  '''
  <h1>Heading 1</h1>
  <h2>Heading 2</h2>
  <h3>Heading 3</h3>
  <!-- 随意添加内容 -->
  ''',

  // 其他参数为可选参数,几个重要的参数:

  // 指定元素的自定义样式
  // 详见支持的内联样式
  customStylesBuilder: (element) {
    if (element.classes.contains('foo')) {
      return {'color': 'red'};
    }

    return null;
  },

  // 渲染自定义小部件
  customWidgetBuilder: (element) {
    if (element.attributes['foo'] == 'bar') {
      return FooBarWidget();
    }

    return null;
  },

  // 当复杂元素加载时或无法呈现时调用这些回调,允许应用程序呈现进度指示器和回退小部件
  onErrorBuilder: (context, element, error) => Text('$element error: $error'),
  onLoadingBuilder: (context, element, loadingProgress) => CircularProgressIndicator(),

  // 用户点击链接时触发此回调
  onTapUrl: (url) => print('tapped $url'),

  // 选择HTML主体的渲染模式
  // 默认情况下,会渲染一个简单的 `Column`
  // 考虑使用 `ListView` 或 `SliverList` 以获得更好的性能
  renderMode: RenderMode.column,

  // 设置文本的默认样式
  textStyle: TextStyle(fontSize: 14),
),

特性

HTML标签

以下标签具有特殊含义/样式,其他所有标签将被解析为文本。

  • A: 下划线,主题强调色,并支持锚点滚动
  • H1/H2/H3/H4/H5/H6
  • IMG: 支持资源 (asset://)、数据URI、本地文件 (file://) 和网络图像
  • LI/OL/UL:
    • 属性: type, start, reversed
    • 内联样式 list-style-type: lower-alpha, upper-alpha, lower-latin, upper-latin, circle, decimal, disc, lower-roman, upper-roman, square
  • TABLE/CAPTION/THEAD/TBODY/TFOOT/TR/TD/TH:
    • TABLE属性: border, cellpadding, cellspacing
    • TD/TH属性: colspan, rowspan, valign
  • ABBR, ACRONYM, ADDRESS, ARTICLE, ASIDE, B, BIG, BLOCKQUOTE, BR, CENTER, CITE, CODE, DD, DEL, DETAILS, DFN, DIV, DL, DT, EM, FIGCAPTION, FIGURE, FONT, FOOTER, HEADER, HR, I, INS, KBD, MAIN, MARK, NAV, NOSCRIPT, P, PRE, Q, RP, RT, RUBY, S, SAMP, SECTION, SMALL, STRIKE, STRONG, STYLE, SUB, SUMMARY, SUP, TT, U, VAR
属性
  • align: center/end/justify/left/right/start/-moz-center/-webkit-center
  • dir: auto/ltr/rtl
内联样式
  • background: 1值(颜色)
  • border: 3值(宽度 样式 颜色),2值(宽度 样式)或1值(宽度)
  • border-radius: 4, 3, 2或1值,支持斜杠(例如 10px / 20px
  • box-sizing: border-box/content-box
  • color: 十六进制值,rgb()hsl() 或命名颜色
  • direction (类似于 dir 属性)
  • font-family
  • font-size: 绝对值(例如 xx-large),相对值(larger, smaller)或在 em, %, ptpx 中的值
  • font-style: italic/normal
  • font-weight: bold/normal/100…900
  • line-height: normal, 数字 或在 em, %, ptpx 中的值
  • margin: 4值,2值或1值在 em, ptpx
  • padding: 4值,2值或1值在 em, ptpx
  • vertical-align: baseline/top/bottom/middle/sub/super
  • text-align (类似于 align 属性)
  • text-decoration
    • text-decoration-color
    • text-decoration-line: line-through/none/overline/underline
    • text-decoration-style: dotted/dashed/double/solid
    • text-decoration-thickness, text-decoration-width: 百分比值
  • text-overflow: clip/ellipsis. 注意: text-overflow: ellipsis 应与 max-lines-webkit-line-clamp 结合使用以获得更好的效果。
  • white-space: normal/pre
  • sizing: auto 或在 em, %, ptpx 中的值
    • width, max-width, min-width
    • height, max-height, min-height

可扩展性

该包实现了具有高测试覆盖率的小部件构建逻辑,以确保正确性。它尝试通过使用具有特定 TextStyleRichText 来构建最优树,合并文本跨度,显示大小化的图像等。理念是构建一个坚实的基础,以便应用程序轻松定制。有以下两种方式来改变输出的小部件树。

  1. 使用像 customStylesBuildercustomWidgetBuilder 这样的回调进行小变化
  2. 使用自定义的 WidgetFactory 对整个渲染过程进行全面控制

增强版包(flutter_widget_from_html)使用了一个带有预建混合物的自定义 WidgetFactory,便于使用:

  • fwfh_cached_network_image 用于优化图像渲染
  • fwfh_chewie 用于视频支持
  • fwfh_just_audio 用于音频支持
  • fwfh_svg 用于SVG支持
  • fwfh_url_launcher 用于启动URL
  • fwfh_webview 用于IFRAME支持

回调

对于颜色、斜体等外观更改,可以使用 customStylesBuilder 指定每个DOM元素的内联样式(参见上述支持列表)。一些常见的条件:

  • 如果HTML标签是H1 <element.localName == 'h1'>
  • 如果元素包含CSS类foo <element.classes.contains('foo')>
  • 如果属性具有特定值 <element.attributes['x'] == 'y'>

这个例子改变了CSS类的颜色:

HtmlWidget(
  'Hello <span class="name">World</span>!',
  customStylesBuilder: (element) {
    if (element.classes.contains('name')) {
      return {'color': 'red'};
    }
    return null;
  },
),

对于简单的自定义小部件,使用 customWidgetBuilder。您需要手动处理DOM元素及其子元素。这个例子渲染了一个轮播图(在线演示在线试用):

自定义 WidgetFactory

HTML字符串被解析为DOM元素,每个元素会被访问一次以收集 BuildMetadata 并准备 BuildBits。以下是它的逐步工作流程:

步骤 描述 集成点
1 解析 WidgetFactory.parse(BuildMetadata)
2 通知父级 BuildOp.onChild(BuildMetadata)
3 填充默认样式 BuildOp.defaultStyles(Element)
4 填充自定义样式 HtmlWidget.customStylesBuilder
5 解析样式键+值对,parseStyle 可能会被多次调用 WidgetFactory.parseStyle(BuildMetadata, String, String), WidgetFactory.parseStyleDisplay(BuildMetadata, String)
6 a. 如果提供了自定义小部件,则转到7 HtmlWidget.customWidgetBuilder
b. 循环遍历子元素以准备 BuildBits
7 通知构建操作 BuildOp.onTree(BuildMetadata, BuildTree)
8 a. 如果不是块元素,则跳到10
b. 使用 Flattener 构建来自 bits 的小部件 BuildOp.onTreeFlattening(BuildMetadata, BuildTree)
9 通知构建操作 BuildOp.onWidgets(BuildMetadata, Iterable<Widget>)
10 结束

注意:

  • 文本相关样式的更改可以通过 TextStyleBuilder 来实现,注册回调以在构建上下文准备好后被调用。
  • 根样式可以通过覆盖 WidgetFactory.onRoot(TextStyleBuilder) 来自定义。
  • 其他复杂的样式可以通过 BuildOp 来支持。

示例代码:

// 简单的回调设置主题强调色
meta.tsb((parent, _) =>
  parent.copyWith(
    style: parent.style.copyWith(
      color: parent.getDependency<ThemeData>().accentColor,
    ),
  ));

// 回调使用第二个参数设置高度
TextStyleHtml callback(TextStyleHtml parent, double value) =>
  parent.copyWith(height: value);

// 注册时传递一些值
meta.tsb<double>(callback, 2.0);

每个元数据可能需要多个tsb回调和构建操作。

以下示例将表情符号内联图像替换为表情符号:

const kHtml = """
<p>Hello <img class="smilie smilie-1" alt=":)" src="http://domain.com/sprites.png" />!</p>
<p>How are you <img class="smilie smilie-2" alt=":P" src="http://domain.com/sprites.png" ?>?
""";

const kSmilies = {':)': '🙂'};

class SmilieScreen extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) => Scaffold(
        appBar: AppBar(
          title: Text('SmilieScreen'),
        ),
        body: Padding(
          padding: const EdgeInsets.all(8.0),
          child: HtmlWidget(
            kHtml,
            factoryBuilder: () => _SmiliesWidgetFactory(),
          ),
        ),
      );
}

class _SmiliesWidgetFactory extends WidgetFactory {
  final smilieOp = BuildOp(
    onTree: (meta, tree) {
      final alt = meta.element.attributes['alt'];
      tree.addText(kSmilies[alt] ?? alt);
    },
  );

  [@override](/user/override)
  void parse(BuildMetadata meta) {
    final e = meta.element;
    if (e.localName == 'img' &&
        e.classes.contains('smilie') &&
        e.attributes.containsKey('alt')) {
      meta.register(smilieOp);
      return;
    }

    return super.parse(meta);
  }
}

更多关于Flutter HTML内容渲染插件flutter_widget_from_html_core_nic的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter HTML内容渲染插件flutter_widget_from_html_core_nic的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,flutter_widget_from_html_core_nic 是一个用于在 Flutter 中渲染 HTML 内容的强大插件。它提供了灵活的方式来将 HTML 字符串转换为 Flutter 小部件。以下是一个简单的代码示例,展示了如何使用 flutter_widget_from_html_core_nic 来渲染 HTML 内容。

首先,确保你已经在 pubspec.yaml 文件中添加了依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_widget_from_html_core_nic: ^x.y.z  # 请替换为最新版本号

然后,运行 flutter pub get 来获取依赖。

接下来,在你的 Dart 文件中,你可以使用以下代码来渲染 HTML 内容:

import 'package:flutter/material.dart';
import 'package:flutter_widget_from_html_core_nic/flutter_widget_from_html_core_nic.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter HTML Renderer'),
        ),
        body: HtmlWidget(
          data: """
            <h1>Hello, World!</h1>
            <p>This is a paragraph with some <strong>bold</strong> and <em>italic</em> text.</p>
            <ul>
              <li>Item 1</li>
              <li>Item 2</li>
              <li>Item 3</li>
            </ul>
            <img src="https://via.placeholder.com/150" alt="Placeholder Image" />
          """,
          // Optional: Customize rendering behavior
          customRender: {
            // Example: Customize image rendering
            "img": (context, element, child, attributes, renderContext) {
              return Image.network(
                attributes['src'] ?? '',
                alt: attributes['alt'],
                width: double.tryParse(attributes['width'] ?? '0'),
                height: double.tryParse(attributes['height'] ?? '0'),
              );
            },
          },
        ),
      ),
    );
  }
}

在这个示例中:

  1. 我们导入了 flutter_widget_from_html_core_nic 包。
  2. 创建了一个简单的 Flutter 应用,其中包含一个 HtmlWidget
  3. HtmlWidgetdata 属性包含要渲染的 HTML 字符串。
  4. 可选地,通过 customRender 参数自定义特定 HTML 标签的渲染行为。在这个例子中,我们自定义了 img 标签的渲染,使用 Image.network 来加载网络图片。

运行这个示例,你应该能看到一个包含标题、段落、列表和图片的页面。

这个插件还支持许多其他功能和自定义选项,你可以查阅其官方文档以了解更多详细信息和高级用法。

回到顶部