Flutter HTML渲染插件flutter_html_v3的使用
Flutter HTML渲染插件flutter_html_v3的使用
简介
flutter_html
是一个用于将HTML和CSS渲染为Flutter小部件的库。它支持多种HTML标签和CSS属性,并允许开发者自定义渲染行为。
安装
在你的 pubspec.yaml
文件中添加以下依赖项:
dependencies:
flutter_html: ^3.0.0-alpha.5
// 或者
// flutter_html_all: ^3.0.0-alpha.5 包括表格、视频、音频、iframe等
支持的HTML标签
标签 | 描述 |
---|---|
<a> |
锚点链接 |
<abbr> |
缩写词 |
<acronym> |
首字母缩略词 |
<address> |
地址信息 |
<article> |
文章 |
<aside> |
侧边栏 |
<audio> |
音频 |
<b> |
加粗文本 |
<bdi> |
文本方向隔离 |
<bdo> |
文本方向覆盖 |
<big> |
大字体文本 |
<blockquote> |
引用块 |
<body> |
文档主体 |
<br> |
换行符 |
<caption> |
表格标题 |
<cite> |
引用 |
<code> |
代码片段 |
<data> |
数字数据 |
<dd> |
详细描述 |
<del> |
删除线文本 |
<details> |
详情 |
<dfn> |
定义 |
<div> |
分区容器 |
<dl> |
定义列表 |
<dt> |
定义项 |
<em> |
强调文本 |
<figcaption> |
图片说明 |
<figure> |
图片或图表 |
<footer> |
页脚 |
<font> |
字体样式 |
<h1> |
一级标题 |
<h2> |
二级标题 |
<h3> |
三级标题 |
<h4> |
四级标题 |
<h5> |
五级标题 |
<h6> |
六级标题 |
<header> |
页眉 |
<hr> |
水平线 |
<i> |
斜体文本 |
<iframe> |
嵌入框架 |
<img> |
图像 |
<ins> |
下划线文本 |
<kbd> |
键盘输入 |
<li> |
列表项 |
<main> |
主要内容 |
<mark> |
标记文本 |
<nav> |
导航链接 |
<noscript> |
不支持脚本时的内容 |
<ol> |
有序列表 |
<p> |
段落 |
<pre> |
预格式化文本 |
<q> |
引用 |
<rp> |
Ruby注音 |
<rt> |
Ruby注音文本 |
<ruby> |
Ruby注音 |
<s> |
删除线文本 |
<samp> |
样本输出 |
<section> |
节 |
<small> |
小字体文本 |
<span> |
内联容器 |
<strike> |
删除线文本 |
<strong> |
加强文本 |
<sub> |
下标 |
<sup> |
上标 |
<summary> |
摘要 |
<svg> |
SVG图像 |
<table> |
表格 |
<tbody> |
表格主体 |
<td> |
单元格 |
<template> |
模板 |
<tfoot> |
表格底部 |
<th> |
表头单元格 |
<thead> |
表头 |
<time> |
时间 |
<tr> |
行 |
<tt> |
打字机风格文本 |
<ul> |
无序列表 |
<var> |
变量 |
<video> |
视频 |
<math> |
MathML公式 |
<mrow> |
MathML公式元素 |
<msup> |
MathML上标 |
<msub> |
MathML下标 |
<mover> |
MathML上标 |
<munder> |
MathML下标 |
<msubsup> |
MathML上下标 |
<moverunder> |
MathML上下标 |
<mfrac> |
MathML分数 |
<mlongdiv> |
MathML长除法 |
<msqrt> |
MathML平方根 |
<mroot> |
MathML根号 |
<mi> |
MathML标识符 |
<mn> |
MathML数字 |
<mo> |
MathML操作符 |
支持的CSS属性
属性 | 描述 |
---|---|
background-color |
背景颜色 |
color |
文本颜色 |
direction |
文本方向 |
display |
显示类型 |
font-family |
字体系列 |
font-feature-settings |
字体特性 |
font-size |
字体大小 |
font-style |
字体样式 |
font-weight |
字体粗细 |
height |
高度 |
letter-spacing |
字母间距 |
line-height |
行高 |
list-style-type |
列表项目符号类型 |
list-style-position |
列表项目符号位置 |
padding |
内边距 |
margin |
外边距 |
text-align |
文本对齐方式 |
text-decoration |
文本修饰 |
text-decoration-color |
文本修饰颜色 |
text-decoration-style |
文本修饰样式 |
text-decoration-thickness |
文本修饰厚度 |
text-shadow |
文本阴影 |
vertical-align |
垂直对齐 |
white-space |
白空间处理 |
width |
宽度 |
word-spacing |
字符间距 |
支持的内联CSS属性
属性 | 描述 |
---|---|
background-color |
背景颜色 |
border (包括特定方向) |
边框 |
color |
文本颜色 |
direction |
文本方向 |
display |
显示类型 |
font-family |
字体系列 |
font-feature-settings |
字体特性 |
font-size |
字体大小 |
font-style |
字体样式 |
font-weight |
字体粗细 |
line-height |
行高 |
list-style-type |
列表项目符号类型 |
list-style-position |
列表项目符号位置 |
padding (包括特定方向) |
内边距 |
margin (包括特定方向) |
外边距 |
text-align |
文本对齐方式 |
text-decoration |
文本修饰 |
text-decoration-color |
文本修饰颜色 |
text-decoration-style |
文本修饰样式 |
text-shadow |
文本阴影 |
使用示例
数据参数
Widget html = Html(
data: """
<div>
<h1>Demo Page</h1>
<p>This is a fantastic product that you should buy!</p>
<h3>Features</h3>
<ul>
<li>It actually works</li>
<li>It exists</li>
<li>It doesn't cost much!</li>
</ul>
<!--You can pretty much put any html in here!-->
</div>
""",
);
文档参数
import 'package:html/parser.dart' as htmlparser;
import 'package:html/dom.dart' as dom;
String htmlData = """
<div>
<h1>Demo Page</h1>
<p>This is a fantastic product that you should buy!</p>
<h3>Features</h3>
<ul>
<li>It actually works</li>
<li>It exists</li>
<li>It doesn't cost much!</li>
</ul>
<!--You can pretty much put any html in here!-->
</div>
""";
dom.Document document = htmlparser.parse(htmlData);
Widget html = Html(
document: document,
);
链接点击事件
Widget html = Html(
data: """
<p>
Linking to <a href='https://github.com'>websites</a> has never been easier.
</p>
""",
onLinkTap: (String? url, RenderContext context, Map<String, String> attributes, dom.Element? element) {
// 打开URL到WebView,或者在浏览器中打开URL,或者其他逻辑
}
);
自定义渲染
Widget html = Html(
data: """
<h3>Display bird element and flutter element <bird></bird></h3>
<flutter></flutter>
<flutter horizontal></flutter>
""",
customRenders: {
birdMatcher(): CustomRender.inlineSpan(inlineSpan: (context, buildChildren) => TextSpan(text: "🐦")),
flutterMatcher(): CustomRender.widget(widget: (context, buildChildren) => FlutterLogo(
style: (context.tree.element!.attributes['horizontal'] != null)
? FlutterLogoStyle.horizontal
: FlutterLogoStyle.markOnly,
textColor: context.style.color!,
size: context.style.fontSize!.size! * 5,
)),
},
tagsList: Html.tags..addAll(["bird", "flutter"]),
);
CustomRenderMatcher birdMatcher() => (context) => context.tree.element?.localName == 'bird';
CustomRenderMatcher flutterMatcher() => (context) => context.tree.element?.localName == 'flutter';
图片加载错误处理
Widget html = Html(
data: """
<img alt='Alt Text of an intentionally broken image' src='https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_92x30d'/>
""",
onImageError: (Exception exception, StackTrace stackTrace) {
FirebaseCrashlytics.instance.recordError(exception, stackTrace);
},
);
图片点击事件
Widget html = Html(
data: """
<img alt='Google' src='https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png' />
""",
onImageTap: (String? url, RenderContext context, Map<String, String> attributes, dom.Element? element) {
// 打开图片到WebView,或者在浏览器中打开图片,或者其他逻辑
}
);
渲染指定标签
Widget html = Html(
data: """
<p>Render this item</p>
<span>Do not render this item or any other item</span>
<img src='https://flutter.dev/images/flutter-mono-81x100.png'/>
""",
tagsList: ['p']
);
自定义样式
Widget html = Html(
data: """
<h1>Table support:</h1>
<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<br>Rowspan<br>Rowspan<br>Rowspan<br>Rowspan<br>Rowspan<br>Rowspan<br>Rowspan<br>Rowspan<br>Rowspan</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>
""",
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元素文本颜色
"h1": Style(color: Colors.red),
}
);
自定义渲染示例
自定义HTML标签
Widget html = Html(
data: """
<h3>Display bird element and flutter element <bird></bird></h3>
<flutter></flutter>
<flutter horizontal></flutter>
""",
customRenders: {
birdMatcher(): CustomRender.inlineSpan(inlineSpan: (context, buildChildren) => TextSpan(text: "🐦")),
flutterMatcher(): CustomRender.widget(widget: (context, buildChildren) => FlutterLogo(
style: (context.tree.element!.attributes['horizontal'] != null)
? FlutterLogoStyle.horizontal
: FlutterLogoStyle.markOnly,
textColor: context.style.color!,
size: context.style.fontSize!.size! * 5,
)),
},
tagsList: Html.tags..addAll(["bird", "flutter"]),
);
CustomRenderMatcher birdMatcher() => (context) => context.tree.element?.localName == 'bird';
CustomRenderMatcher flutterMatcher() => (context) => context.tree.element?.localName == 'flutter';
自定义iframe渲染
Widget html = Html(
data: """
<h3>Google iframe:</h3>
<iframe src="https://google.com"></iframe>
<h3>YouTube iframe:</h3>
<iframe src="https://www.youtube.com/embed/tgbNymZ7vqY"></iframe>
""",
customRenders: {
iframeYT(): CustomRender.widget(widget: (context, buildChildren) {
double? width = double.tryParse(context.tree.attributes['width'] ?? "");
double? height = double.tryParse(context.tree.attributes['height'] ?? "");
return Container(
width: width ?? (height ?? 150) * 2,
height: height ?? (width ?? 300) / 2,
child: WebView(
initialUrl: context.tree.attributes['src']!,
javascriptMode: JavascriptMode.unrestricted,
navigationDelegate: (NavigationRequest request) async {
// 当显示嵌入式YouTube视频时,不需要加载其他URL,因此阻止URL加载
if (!request.url.contains("youtube.com/embed")) {
return NavigationDecision.prevent;
} else {
return NavigationDecision.navigate;
}
},
),
);
}),
iframeOther(): CustomRender.widget(widget: (context, buildChildren) {
double? width = double.tryParse(context.tree.attributes['width'] ?? "");
double? height = double.tryParse(context.tree.attributes['height'] ?? "");
return Container(
width: width ?? (height ?? 150) * 2,
height: height ?? (width ?? 300) / 2,
child: WebView(
initialUrl: context.tree.attributes['src'],
javascriptMode: JavascriptMode.unrestricted,
// 其他iframe内容可能需要滚动,因此使用VerticalDragGestureRecognizer
gestureRecognizers: [
Factory(() => VerticalDragGestureRecognizer())
].toSet(),
),
);
}),
iframeNull(): CustomRender.widget(widget: (context, buildChildren) => Container(height: 0, width: 0)),
}
);
CustomRenderMatcher iframeYT() => (context) => context.tree.element?.attributes['src']?.contains("youtube.com/embed") ?? false;
CustomRenderMatcher iframeOther() => (context) => !(context.tree.element?.attributes['src']?.contains("youtube.com/embed")
?? context.tree.element?.attributes['src'] == null);
CustomRenderMatcher iframeNull() => (context) => context.tree.element?.attributes['src'] == null;
更多关于Flutter HTML渲染插件flutter_html_v3的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter HTML渲染插件flutter_html_v3的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
flutter_html
是一个用于在 Flutter 应用中渲染 HTML 内容的插件。它支持大部分的 HTML 标签,并且可以自定义样式和渲染行为。flutter_html
的第三个版本(flutter_html_v3
)在性能和功能上都有所提升。
以下是使用 flutter_html_v3
的基本步骤:
1. 添加依赖
首先,在你的 pubspec.yaml
文件中添加 flutter_html
依赖:
dependencies:
flutter:
sdk: flutter
flutter_html: ^3.0.0-alpha.2
然后运行 flutter pub get
来安装依赖。
2. 基本使用
在你的 Flutter 应用中,你可以使用 Html
组件来渲染 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(
home: Scaffold(
appBar: AppBar(
title: Text('Flutter HTML Example'),
),
body: SingleChildScrollView(
child: Html(
data: """
<h1>Heading 1</h1>
<p>This is a paragraph with <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" />
<a href="https://flutter.dev">Visit Flutter</a>
""",
),
),
),
);
}
}
3. 自定义样式
你可以通过 style
参数来自定义 HTML 标签的样式。style
参数接受一个 Map<String, Style>
,其中键是 CSS 选择器,值是一个 Style
对象。
Html(
data: """
<h1>Heading 1</h1>
<p>This is a paragraph with <strong>bold</strong> and <em>italic</em> text.</p>
""",
style: {
"h1": Style(
fontSize: FontSize.larger,
fontWeight: FontWeight.bold,
color: Colors.blue,
),
"p": Style(
fontSize: FontSize.medium,
color: Colors.black87,
),
"strong": Style(
fontWeight: FontWeight.bold,
color: Colors.red,
),
"em": Style(
fontStyle: FontStyle.italic,
color: Colors.green,
),
},
)
4. 处理链接和图片
flutter_html
提供了回调函数来处理链接和图片的点击事件。
Html(
data: """
<a href="https://flutter.dev">Visit Flutter</a>
<img src="https://via.placeholder.com/150" alt="Placeholder Image" />
""",
onLinkTap: (url, _, __, ___) {
print("Link tapped: $url");
},
onImageTap: (src, _, __, ___) {
print("Image tapped: $src");
},
)
5. 自定义渲染
如果你需要更高级的自定义渲染,你可以使用 customRender
参数。customRender
允许你为特定的 HTML 标签定义自定义的渲染逻辑。
Html(
data: """
<custom-tag>Custom Content</custom-tag>
""",
customRender: {
"custom-tag": (context, child) {
return Container(
padding: EdgeInsets.all(10),
color: Colors.yellow,
child: Text("Custom Render: ${context.tree.element?.text}"),
);
},
},
)