Flutter 和 InAppWebView 如何获取高度?
Flutter and InAppWebView How to get height?
在flutter中,使用Webview的时候,有时会想在上面和下面显示内容
问题 - 1? Webview 需要约束,否则它无法显示:您需要将 Webview 包装在一个固定大小的容器下或在一个可扩展的列或类似的东西下。
问题 - 2 ?高度可以很容易地获取,但有时 Webview 加载异步数据,如嵌入脚本,这将改变页面的样式。在这种情况下,很难知道如何以及何时获取 Webview 高度。
由于这些问题,大多数时候您的 Webview 会显示一个滚动条,当到达 webview 底部时,用户将无法滚动您的 flutter 页面。滚动会与Webview冲突。
解决这个问题的最佳方法是什么?
您需要在 html 周围添加额外的内容并使用 javascript 事件处理程序。
我们不会将原始 html 传递给 webview,而是对其进行一些自定义。
final htmlFromApi = await getContent();
final html = Uri.dataFromString('''
<html lang="fr">
<meta name="viewport" content="width=device-width user-scalable=no zoom=1.1">
<style>img {max-width: 100%; height: auto}</style>
<body>
<div class="container" id="_flutter_target_do_not_delete">$htmlFromApi</div>
<script>
function outputsize() {
if (typeof window.flutter_inappwebview !== "undefined" && typeof window.flutter_inappwebview.callHandler !== "undefined")
window.flutter_inappwebview.callHandler('newHeight', document.getElementById("_flutter_target_do_not_delete").offsetHeight);
}
new ResizeObserver(outputsize).observe(_flutter_target_do_not_delete)
</script>
</body>
</html>
''', mimeType: "text/html", encoding: Encoding.getByName("utf-8")).toString();
如何使用 Webview :
/// Define it to 1 else the Webview widget will not start loading.
double height = 1;
///some widgets
Container(
height: height,
child: InAppWebView(
initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
supportZoom: false,
javaScriptEnabled: true,
disableHorizontalScroll: true,
disableVerticalScroll: true,
),
),
onWebViewCreated: (InAppWebViewController controller) {
controller.addJavaScriptHandler(
handlerName: "newHeight",
callback: (List<dynamic> arguments) async {
int? height = arguments.isNotEmpty ? arguments[0] : await controller.getContentHeight();
if (mounted) setState(() => this.height = height!.toDouble());
});
},
initialUrl: html,
),
),
///some widgets
解释:
当 div 内容发生变化时,将发送一个具有新大小的事件。 flutter InAppWebView 将监听它并调用回调。我们可以用当前视图高度更新 WebView 的父容器。
就是这样,webview 在 flutter 中显示得像一个小部件,没有任何大小问题。
int? contentHeight = await _controller?.getContentHeight();
double? zoomScale = await _controller?.getZoomScale();
double htmlHeight = contentHeight!.toDouble() * zoomScale!;
double htmlHeightFixed =
double.parse(htmlHeight.toStringAsFixed(2));
if (htmlHeightFixed == 0.0) {
return;
}
setState(() {
_htmlHeight = htmlHeightFixed + 0.1;
});
在flutter中,使用Webview的时候,有时会想在上面和下面显示内容
问题 - 1? Webview 需要约束,否则它无法显示:您需要将 Webview 包装在一个固定大小的容器下或在一个可扩展的列或类似的东西下。
问题 - 2 ?高度可以很容易地获取,但有时 Webview 加载异步数据,如嵌入脚本,这将改变页面的样式。在这种情况下,很难知道如何以及何时获取 Webview 高度。
由于这些问题,大多数时候您的 Webview 会显示一个滚动条,当到达 webview 底部时,用户将无法滚动您的 flutter 页面。滚动会与Webview冲突。
解决这个问题的最佳方法是什么?
您需要在 html 周围添加额外的内容并使用 javascript 事件处理程序。
我们不会将原始 html 传递给 webview,而是对其进行一些自定义。
final htmlFromApi = await getContent();
final html = Uri.dataFromString('''
<html lang="fr">
<meta name="viewport" content="width=device-width user-scalable=no zoom=1.1">
<style>img {max-width: 100%; height: auto}</style>
<body>
<div class="container" id="_flutter_target_do_not_delete">$htmlFromApi</div>
<script>
function outputsize() {
if (typeof window.flutter_inappwebview !== "undefined" && typeof window.flutter_inappwebview.callHandler !== "undefined")
window.flutter_inappwebview.callHandler('newHeight', document.getElementById("_flutter_target_do_not_delete").offsetHeight);
}
new ResizeObserver(outputsize).observe(_flutter_target_do_not_delete)
</script>
</body>
</html>
''', mimeType: "text/html", encoding: Encoding.getByName("utf-8")).toString();
如何使用 Webview :
/// Define it to 1 else the Webview widget will not start loading.
double height = 1;
///some widgets
Container(
height: height,
child: InAppWebView(
initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
supportZoom: false,
javaScriptEnabled: true,
disableHorizontalScroll: true,
disableVerticalScroll: true,
),
),
onWebViewCreated: (InAppWebViewController controller) {
controller.addJavaScriptHandler(
handlerName: "newHeight",
callback: (List<dynamic> arguments) async {
int? height = arguments.isNotEmpty ? arguments[0] : await controller.getContentHeight();
if (mounted) setState(() => this.height = height!.toDouble());
});
},
initialUrl: html,
),
),
///some widgets
解释:
当 div 内容发生变化时,将发送一个具有新大小的事件。 flutter InAppWebView 将监听它并调用回调。我们可以用当前视图高度更新 WebView 的父容器。 就是这样,webview 在 flutter 中显示得像一个小部件,没有任何大小问题。
int? contentHeight = await _controller?.getContentHeight();
double? zoomScale = await _controller?.getZoomScale();
double htmlHeight = contentHeight!.toDouble() * zoomScale!;
double htmlHeightFixed =
double.parse(htmlHeight.toStringAsFixed(2));
if (htmlHeightFixed == 0.0) {
return;
}
setState(() {
_htmlHeight = htmlHeightFixed + 0.1;
});