Flutter和InAppWebView如何获得高度?

vd8tlhqk  于 2022-12-05  发布在  Flutter
关注(0)|答案(3)|浏览(391)

在flutter中,当使用Webview时,您有时希望显示其上下的内容。
问题-1-Webview需要约束,否则无法显示:您需要将Webview Package 在一个固定大小的容器下或一个可扩展的列下。
问题2?高度很容易获取,但有时Webview会加载异步数据,如嵌入脚本,这将改变页面的样式。在这种情况下,很难知道如何以及何时获取Webview高度。
有了这些问题,大多数时候你的网页视图会显示一个滚动条,当到达网页视图的底部时,用户将很难滚动你的Flutter页面。滚动将与网页视图冲突。
解决这个问题的最佳方法是什么?

d8tt03nd

d8tt03nd1#

您将需要在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中显示得像一个小部件,没有任何大小问题。

jdzmm42g

jdzmm42g2#

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;
            });
u7up0aaq

u7up0aaq3#

2022年12月更新!!

///
      double webViewHeight = 1;

      WebViewController? controller;

      WebView(
        initialUrl: widget.url,
        onWebViewCreated: (WebViewController c) {
          controller = c;
        },
        onPageFinished: (_) {
          updateHeight();
        },
        javascriptMode: JavascriptMode.unrestricted,
      );

     // This calculates the height
     void updateHeight() async {
       double height = double.parse(await 
          controller!.runJavascriptReturningResult('document.documentElement.scrollHeight;'));
       print(height); // prints height
     }

在此基础上,我创建了一个小部件,您可以将其放置在列表视图或任何可滚动区域中。它可以自动检测高度并自行设置

class DynamicHeightWebView extends StatefulWidget {
  ///
  final String url;

  ///
  const DynamicHeightWebView({Key? key, required this.url}) : super(key: key);

  @override
  State<DynamicHeightWebView> createState() => _DynamicHeightWebViewState();
}

class _DynamicHeightWebViewState extends State<DynamicHeightWebView>
    with AutomaticKeepAliveClientMixin {
  ///
  double webViewHeight = 1;

  WebViewController? controller;

  @override
  Widget build(BuildContext context) {
    super.build(context);
    return SizedBox(
      height: webViewHeight,
      child: WebView(
        initialUrl: widget.url,
        onWebViewCreated: (WebViewController c) {
          controller = c;
        },
        onPageFinished: (_) {
          updateHeight();
        },
        javascriptMode: JavascriptMode.unrestricted,
      ),
    );
  }

  void updateHeight() async {
    double height = double.parse(await controller!.runJavascriptReturningResult(
        'document.documentElement.scrollHeight;'));
    if (webViewHeight != height) {
      setState(() {
        webViewHeight = height;
      });
    }
  }

  @override
  bool get wantKeepAlive => true;
}

如果需要,可以删除AutomaticKeepAliveClientMixin

相关问题