Flutter之WebView加载html字符串及高度自适应
Flutter 官方提供了 webview_flutter 插件用于加载 html 页面,网上有很多使用该插件的 WebView
控件通过 url 加载 html 页面的资料教程,但是加载 html 字符串的资料则相对较少。本篇文章主要讲解如何使用 webview_flutter
插件提供的 WebView
加载 html 字符串。
使用场景
什么时候在开发中会用到使用 WebView
来加载 html 字符串呢?这里举一个笔者在真实项目中遇到的需求,PC 端使用富文本编辑器编辑提交的内容需要在 App 中进行展示,因服务端存储/返回给 App 的就是一段 html 字符串,此时 App 就需要用到 WebView 来对这段 html 字符串内容进行加载显示。
WebView 加载 Html 字符串
添加依赖
在项目的 pubspec.yaml
文件中添加 webview_flutter
插件的依赖:
dependencies:
webview_flutter: ^3.0.0
加载 html 字符串
导入 webview_flutter
的包:
import 'package:webview_flutter/webview_flutter.dart';
然后使用时直接创建一个 WebView
对象即可。
WebView
构造参数有一个 initialUrl
参数,可以通过该参数传入一个 url 地址加载 html 页面,如下:

但是 WebView
的构造函数中并没有加载 html 字符串的参数,所以无法在创建 WebView
的时候直接加载 html 字符串,需要用到 WebViewController
来进行加载 html 字符串。
WebViewController
提供了 loadHtmlString
或者 loadUrl
方法来加载 html 字符串, WebViewController
需要通过 WebView
的 onWebViewCreated
回调获取,如下:
WebView(
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (WebViewController controller){
//获取到 WebViewController
},
)
loadHtmlString
通过 WebViewController
的 loadHtmlString
方法加载 html 字符串,参数传入 html 字符串即可,如下:
效果如下:

内容确实加载出来了,但是文字特别小,那是因为在 iOS 上需要在 html 里加上 <meta name="viewport" content="width=device-width, initial-scale=1.0">
否则默认字体会特别小。修改如下:
效果如下:

除此之外,loadHtmlString
还有一个可选参数 baseUrl
,作用是当 html 字符串中使用到了相对路径的 url 时,设置了 baseUrl
后 WebView 加载 html 请求相应 url 时就会带上 baseUrl,如 html 字符串中有显示图片,图片地址写的是相对路径,此时就可以使用 baseUrl 参数来解决,如下:
效果如下:

loadUrl
除了使用 loadHtmlString
外, 还可以使用 loadUrl
来加载 html 字符串,看到这里可能有些人就会有疑问,loadUrl
不是加载 url 的么怎么也能用来加载 html 字符串? 确实是可以的,但是需要通过 Uri.dataFromString
进行转换。如下:
WebView(
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (WebViewController controller){
controller.loadUrl(Uri.dataFromString(html, mimeType: "text/html", encoding: utf8,).toString());
},
)
通过 Uri.dataFromString
转换同样可实现加载 html 字符串,需要注意的是 Uri.dataFromString
除了 html 字符串的参数外,还需要设置 mimeType
为 "text/html"
和 encoding
为 utf8
,如果不设置 encoding
加载时可能会报错,而不设置 mimeType
则会直接把 html 代码加载出来。
WebView 高度自适应
WebView
默认无法做到高度自适应,即根据 html 内容高度自适应,当在 Column
等控件中使用 WebView
而不手动设置固定高度时则会报错。
如果要做到高度自适应,则需要用到 js 方法,在 html 中通过 js 监听页面大小的变化,然后获取页面高度再将高度传递到 Flutter 中,在 Flutter 中获取到高度后再动态改变 WebView 的高度。
实现步骤如下:
- 给 WebView 添加一个
JavascriptChannel
用于 js 与 Flutter 通信 - 在 html 中添加
script
使用ResizeObserver
监听body
元素的大小变化,在变化回调里调用上一步添加的JavascriptChannel
发送页面高度的消息 - 在 Flutter 中接收到消息时,获取 js 发送过来的高度值,然后更新 WebView 的高度
代码如下:
如上,给 WebView
外面包了一层 SizeBox
用于限制 WebView
的高度,同时给 WebView
添加了名为 Resize
的 JavascriptChannel
, 在 html 字符串中添加了 script
使用 js 的 ResizeObserver
监听页面元素大小变化,在变化回调里获取元素的 scrollHeight
值并将其发送到 Flutter,在 Flutter 的 JavascriptChannel
消息回调里获取高度值并更新 SizeBox 的高度。从而实现了 WebView
的高度自适应。
完整代码
转载自:https://juejin.cn/post/7056353175900520462