Flutter和InAppWebView如何获取高度?

Eng*_*Eng 3 flutter flutter-inappwebview

在flutter中,使用Webview时,有时希望显示其上方和下方的内容。

问题-1?Webview 需要约束,否则无法显示:您需要将 Webview 包装在具有固定大小的容器下或具有可扩展或类似内容的列下。

问题-2?高度可以很容易获取,但有时 Webview 会加载异步数据,例如嵌入脚本,这会改变页面的样式。在这种情况下,很难知道如何以及何时获取 Webview 高度。

有了这些问题,大多数时候你的 Webview 会显示一个滚动条,当到达 Webview 的底部时,用户将无法滚动你的 flutter 页面。滚动会与Webview冲突。

解决这个问题的最佳方法是什么?

Eng*_*Eng 12

您需要在 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();
Run Code Online (Sandbox Code Playgroud)

如何使用 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
Run Code Online (Sandbox Code Playgroud)

解释 :

当 div 内容发生更改时,将发送包含新大小的事件。flutter InAppWebView 会监听它并调用回调。我们只需使用当前视图高度更新 WebView 的父容器即可。就这样,webview 像 flutter 中的小部件一样显示,没有任何大小问题。