Flutter HTML内容渲染插件flutter_html的使用
Flutter HTML内容渲染插件flutter_html的使用
安装
在你的 pubspec.yaml
文件中添加以下依赖:
dependencies:
flutter_html: ^2.2.1
目前支持的HTML标签
目前flutter_html支持以下HTML标签:
标签 | 描述 |
---|---|
<a> |
超链接 |
<abbr> |
缩写词 |
<acronym> |
首字母缩略词 |
<address> |
联系信息 |
<article> |
独立的内容 |
<aside> |
侧边栏内容 |
<audio> |
音频 |
<b> |
粗体文本 |
<bdi> |
隔离文本方向 |
<bdo> |
文本方向覆盖 |
<big> |
大字体 |
… |
目前支持的CSS属性
目前flutter_html支持以下CSS属性:
属性 | 描述 |
---|---|
background-color |
背景颜色 |
color |
文本颜色 |
direction |
文本方向 |
display |
显示类型 |
font-family |
字体系列 |
font-feature-settings |
字体特征设置 |
font-size |
字体大小 |
… |
目前支持的内联CSS属性
目前flutter_html支持以下内联CSS属性:
属性 | 描述 |
---|---|
background-color |
背景颜色 |
border |
边框 |
color |
文本颜色 |
direction |
文本方向 |
display |
显示类型 |
font-family |
字体系列 |
font-size |
字体大小 |
… |
为什么选择这个包?
这个包的设计初衷是为了简化HTML内容到Flutter控件树的渲染。它不仅支持基本样式,还提供了可选的自定义API来实现对控件渲染的精细控制。
API 参考
对于完整的API参考,请参阅 这里。
构造函数
该包当前有两个不同的构造函数:Html()
和 Html.fromDom()
。
Html()
构造函数适用于直接从源传递HTML数据。Html.fromDom()
构造函数允许你在渲染之前修改或清理HTML数据。
参数
以下是 Html
小部件接受的主要参数及其描述:
Widget html = Html(
data: htmlData, // HTML数据字符串
onLinkTap: (String? url, RenderContext context, Map<String, String> attributes, dom.Element? element) {
// 打开URL的逻辑
},
customRender: {
"table": (context, child) {
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: (context.tree as TableLayoutElement).toWidget(context),
);
}
},
onImageError: (Exception exception, StackTrace stackTrace) {
// 图像加载错误的处理逻辑
},
onImageTap: (String? url, RenderContext context, Map<String, String> attributes, dom.Element? element) {
// 图像点击的处理逻辑
},
tagsList: Html.tags..addAll(["bird", "flutter"]), // 要渲染的HTML标签列表
style: {
"table": Style(backgroundColor: Color.fromARGB(0x50, 0xee, 0xee, 0xee)),
"tr": Style(border: Border(bottom: BorderSide(color: Colors.grey))),
"th": Style(padding: EdgeInsets.all(6), backgroundColor: Colors.grey),
"td": Style(padding: EdgeInsets.all(6), alignment: Alignment.topLeft),
"h1": Style(color: Colors.red),
},
customImageRender: {
networkSourceMatcher(domains: ["flutter.dev"]): (context, attributes, element) {
return FlutterLogo(size: 36);
},
networkSourceMatcher(domains: ["mydomain.com"]): networkImageRender(
headers: {"Custom-Header": "some-value"},
altWidget: (alt) => Text(alt ?? ""),
loadingWidget: () => Text("Loading..."),
),
(attr, _) => attr["src"] != null && attr["src"]!.startsWith("/wiki"):
networkImageRender(mapUrl: (url) => "https://upload.wikimedia.org" + url!),
networkSourceMatcher(): networkImageRender(altWidget: (_) => FlutterLogo()),
},
);
示例代码
下面是一个完整的示例代码,展示了如何使用 flutter_html
渲染复杂的HTML内容:
import 'package:flutter/material.dart';
import 'package:flutter_html/flutter_html.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(primarySwatch: Colors.deepPurple),
home: MyHomePage(title: 'flutter_html Example'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
[@override](/user/override)
_MyHomePageState createState() => _MyHomePageState();
}
const htmlData = r"""
<p id='top'><a href='#bottom'>Scroll to bottom</a></p>
<h1>Header 1</h1>
<h2>Header 2</h2>
<h3>Header 3</h3>
<h4>Header 4</h4>
<h5>Header 5</h5>
<h6>Header 6</h6>
<h3>Ruby Support:</h3>
<p>
<ruby>
漢<rt>かん</rt>
字<rt>じ</rt>
</ruby>
is Japanese Kanji.
</p>
<h3>Support for maxLines:</h3>
<h5>Lorem ipsum dolor sit amet, consectetur adipiscing elit...</h5>
<h3>Support for <code>sub</code>/<code>sup</code></h3>
Solve for <var>x<sub>n</sub></var>: log<sub>2</sub>(<var>x</var><sup>2</sup>+<var>n</var>) = 9<sup>3</sup>
<p>One of the most <span>common</span> equations in all of physics is <var>E</var>=<var>m</var><var>c</var><sup>2</sup>.</p>
<h3>Inline Styles:</h3>
<p>The should be <span style='color: blue;'>BLUE</span></p>
<p>The should be <span style='color: red;'>RED</span></p>
<p>The should be <span style='color: rgba(0, 0, 0, 0.10);'>BLACK with 10% alpha</span></p>
<p>The should be <span style='color: rgb(0, 97, 0);'>GREEN</span></p>
<p>The should be <span style='background-color: red; color: rgb(0, 97, 0);'>GREEN</span></p>
<p style="text-align: center;"><span style="color: rgba(0, 0, 0, 0.95);">blasdafjklasdlkjfkl</span></p>
<p style="text-align: right;"><span style="color: rgba(0, 0, 0, 0.95);">blasdafjklasdlkjfkl</span></p>
<p style="text-align: justify;"><span style="color: rgba(0, 0, 0, 0.95);">blasdafjklasdlkjfkl</span></p>
<p style="text-align: center;"><span style="color: rgba(0, 0, 0, 0.95);">blasdafjklasdlkjfkl</span></p>
<h3>Table support (with custom styling!):</h3>
<p><q>Famous quote...</q></p>
<table>
<colgroup>
<col width="50%" />
<col span="2" width="25%" />
</colgroup>
<thead>
<tr><th>One</th><th>Two</th><th>Three</th></tr>
</thead>
<tbody>
<tr>
<td rowspan='2'>Rowspan\nRowspan\nRowspan\nRowspan\nRowspan\nRowspan\nRowspan\nRowspan\nRowspan\nRowspan</td><td>Data</td><td>Data</td>
</tr>
<tr>
<td colspan="2"><img alt='Google' src='https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png' /></td>
</tr>
</tbody>
<tfoot>
<tr><td>fData</td><td>fData</td><td>fData</td></tr>
</tfoot>
</table>
<h3>Custom Element Support (inline: <bird></bird> and as block):</h3>
<flutter></flutter>
<flutter horizontal></flutter>
<h3 id='middle'>SVG support:</h3>
<svg id='svg1' viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'>
<circle r="32" cx="35" cy="65" fill="#F00" opacity="0.5"/>
<circle r="32" cx="65" cy="65" fill="#0F0" opacity="0.5"/>
<circle r="32" cx="50" cy="35" fill="#00F" opacity="0.5"/>
</svg>
<h3>List support:</h3>
<ol>
<li>This</li>
<li><p>is</p></li>
<li>an</li>
<li>
ordered
<ul>
<li>With<br/>...<br/></li>
<li>a</li>
<li>nested</li>
<li>unordered
<ol style="list-style-type: lower-alpha;" start="5">
<li>With a nested</li>
<li>ordered list</li>
<li>with a lower alpha list style</li>
<li>starting at letter e</li>
</ol>
</li>
<li>list</li>
</ul>
</li>
<li>list! Lorem ipsum dolor sit amet.</li>
<li><h2>Header 2</h2></li>
<h2><li>Header 2</li></h2>
</ol>
<h3>Link support:</h3>
<p>
Linking to <a href='https://github.com'>websites</a> has never been easier.
</p>
<h3>Image support:</h3>
<h3>Network png</h3>
<img alt='Google' src='https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png' />
<h3>Network svg</h3>
<img src='https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/android.svg' />
<h3>Local asset png</h3>
<img src='asset:assets/html5.png' width='100' />
<h3>Local asset svg</h3>
<img src='asset:assets/mac.svg' width='100' />
<h3>Data uri (with base64 support)</h3>
<img alt='Red dot (png)' src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==' />
<img alt='Green dot (base64 svg)' src='data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB2aWV3Qm94PSIwIDAgMzAgMjAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxjaXJjbGUgY3g9IjE1IiBjeT0iMTAiIHI9IjEwIiBmaWxsPSJncmVlbiIvPgo8L3N2Zz4=' />
<img alt='Green dot (plain svg)' src='data:image/svg+xml,%3C?xml version="1.0" encoding="UTF-8"?%3E%3Csvg viewBox="0 0 30 20" xmlns="http://www.w3.org/2000/svg"%3E%3Ccircle cx="15" cy="10" r="10" fill="yellow"/%3E%3C/svg%3E' />
<h3>Custom source matcher (relative paths)</h3>
<img src='/wikipedia/commons/thumb/e/ef/Octicons-logo-github.svg/200px-Octicons-logo-github.svg.png' />
<h3>Custom image render (flutter.dev)</h3>
<img src='https://flutter.dev/images/flutter-mono-81x100.png' />
<h3>No image source</h3>
<img alt='No source' />
<img alt='Empty source' src='' />
<h3>Broken network image</h3>
<img alt='Broken image' src='https://www.notgoogle.com/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png' />
<h3>MathML Support:</h3>
<math>
<mrow>
<mi>x</mi>
<mo>=</mo>
<mfrac>
<mrow>
<mrow>
<mo>-</mo>
<mi>b</mi>
</mrow>
<mo>&PlusMinus;</mo>
<msqrt>
<mrow>
<msup>
<mi>b</mi>
<mn>2</mn>
</msup>
<mo>-</mo>
<mrow>
<mn>4</mn>
<mo>&InvisibleTimes;</mo>
<mi>a</mi>
<mo>&InvisibleTimes;</mo>
<mi>c</mi>
</mrow>
</mrow>
</msqrt>
</mrow>
<mrow>
<mn>2</mn>
<mo>&InvisibleTimes;</mo>
<mi>a</mi>
</mrow>
</mfrac>
</mrow>
</math>
<math>
<munderover>
<mo>&int;</mo>
<mn>0</mn>
<mi>5</mi>
</munderover>
<msup>
<mi>x</mi>
<mn>2</mn>
</msup>
<mo>&sdot;</mo>
<mi>&dd;</mi><mi>x</mi>
<mo>=</mo>
<mo>[</mo>
<mfrac>
<mn>1</mn>
<mi>3</mi>
</mfrac>
<msup>
<mi>x</mi>
<mn>3</mn>
</msup>
<msubsup>
<mo>]</mo>
<mn>0</mn>
<mn>5</mn>
</msubsup>
<mo>=</mo>
<mfrac>
<mn>125</mn>
<mi>3</mi>
</mfrac>
<mo>-</mo>
<mn>0</mn>
<mo>=</mo>
<mfrac>
<mn>125</mn>
<mi>3</mi>
</mfrac>
</math>
<math>
<msup>
<mo>sin</mo>
<mn>2</mn>
</msup>
<mo>&theta;</mo>
<mo>+</mo>
<msup>
<mo>cos</mo>
<mn>2</mn>
</msup>
<mo>&theta;</mo>
<mo>=</mo>
<mn>1</mn>
</math>
<h3>Tex Support with the custom tex tag:</h3>
<tex>i\hbar\frac{\partial}{\partial t}\Psi(\vec x,t) = -\frac{\hbar}{2m}\nabla^2\Psi(\vec x,t)+ V(\vec x)\Psi(\vec x,t)</tex>
<p id='bottom'><a href='#top'>Scroll to top</a></p>
""";
class _MyHomePageState extends State<MyHomePage> {
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('flutter_html Example'),
centerTitle: true,
),
body: SingleChildScrollView(
child: Html(
data: htmlData,
tagsList: Html.tags..addAll(["bird", "flutter"]),
style: {
"table": Style(backgroundColor: Color.fromARGB(0x50, 0xee, 0xee, 0xee)),
"tr": Style(border: Border(bottom: BorderSide(color: Colors.grey))),
"th": Style(padding: EdgeInsets.all(6), backgroundColor: Colors.grey),
"td": Style(padding: EdgeInsets.all(6), alignment: Alignment.topLeft),
'h5': Style(maxLines: 2, textOverflow: TextOverflow.ellipsis),
},
customRender: {
"table": (context, child) {
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: (context.tree as TableLayoutElement).toWidget(context),
);
},
"bird": (RenderContext context, Widget child) {
return TextSpan(text: "🐦");
},
"flutter": (RenderContext context, Widget child) {
return FlutterLogo(
style: (context.tree.element!.attributes['horizontal'] != null)
? FlutterLogoStyle.horizontal
: FlutterLogoStyle.markOnly,
textColor: context.style.color!,
size: context.style.fontSize!.size! * 5,
);
},
},
customImageRender: {
networkSourceMatcher(domains: ["flutter.dev"]): (context, attributes, element) {
return FlutterLogo(size: 36);
},
networkSourceMatcher(domains: ["mydomain.com"]): networkImageRender(
headers: {"Custom-Header": "some-value"},
altWidget: (alt) => Text(alt ?? ""),
loadingWidget: () => Text("Loading..."),
),
(attr, _) => attr["src"] != null && attr["src"]!.startsWith("/wiki"):
networkImageRender(mapUrl: (url) => "https://upload.wikimedia.org" + url!),
networkSourceMatcher(): networkImageRender(altWidget: (_) => FlutterLogo()),
},
onLinkTap: (url, _, __, ___) {
print("Opening $url...");
},
onImageTap: (src, _, __, ___) {
print(src);
},
onImageError: (exception, stackTrace) {
print(exception);
},
onCssParseError: (css, messages) {
print("css that errored: $css");
print("error messages:");
messages.forEach((element) {
print(element);
});
},
),
),
);
}
}
更多关于Flutter HTML内容渲染插件flutter_html的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter HTML内容渲染插件flutter_html的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何在Flutter应用中使用flutter_html
插件来渲染HTML内容的示例代码。这个插件允许你将HTML字符串直接转换为Flutter的Widget,从而在你的应用中显示复杂的HTML内容。
首先,确保你已经在pubspec.yaml
文件中添加了flutter_html
依赖:
dependencies:
flutter:
sdk: flutter
flutter_html: ^3.0.0 # 请检查最新版本号
然后,运行flutter pub get
来安装依赖。
接下来,你可以在你的Flutter应用中如下使用flutter_html
:
import 'package:flutter/material.dart';
import 'package:flutter_html/flutter_html.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter HTML Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
// 示例HTML内容
final String htmlData = """
<h1>Hello, Flutter!</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" />
""";
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter HTML Demo'),
),
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Html(
data: htmlData,
// 自定义样式(可选)
customRender: (node, children) {
if (node is dom.Element && node.tagName == 'img') {
return Image.network(node.attributes['src'] ?? '');
}
return null; // 返回null以使用默认渲染
},
// 配置更多自定义渲染选项(可选)
customStyleBuilder: (context, element) {
return element.style
..color = Colors.black87
..fontSize = FontSize(16)
..decorationColor = Colors.blue; // 例如,链接颜色
},
),
),
),
);
}
}
在这个示例中:
- HTML内容:我们定义了一个包含标题、段落、列表和图片的HTML字符串。
- Html Widget:使用
Html
widget来渲染这个HTML字符串。 - 自定义渲染:通过
customRender
回调,我们可以自定义特定HTML标签的渲染方式。在这个例子中,我们自定义了<img>
标签的渲染,使其使用Image.network
来显示图片。 - 自定义样式:通过
customStyleBuilder
回调,我们可以自定义HTML元素的样式。在这个例子中,我们设置了文本颜色、字体大小和链接的下划线颜色。
这个示例展示了如何使用flutter_html
插件来渲染基本的HTML内容,并且展示了如何通过自定义渲染和样式来增强功能。根据你的需求,你可以进一步自定义和扩展这些功能。