是否可以自定义Flutter Webview错误消息?

时间:2019-10-21 15:30:00

标签: android ios flutter mobile webview

我正在Flutter中开发WebView移动应用程序,并且我想自定义Webview错误,因为如果客户将关闭其wifi并得到“ net :: ERR_ADDRESS_UNREACHABLE”,那就不好了。因此,我想将此页面更改为某些自定义设计,并显示类似“此应用程序需要Internet连接,您应该打开wifi”之类的东西。

像这样可能吗?我在搜索文档时一无所获。

非常感谢。

2 个答案:

答案 0 :(得分:0)

您可以尝试使用我的插件flutter_inappwebview。在WebView加载URL时(net::ERR_ADDRESS_UNREACHABLE事件)以及接收HTTP错误(例如403、404等)时,它具有管理错误的事件(例如onLoadError)(onLoadHttpError事件)。

这是一个完整的示例,该示例加载名为https://not-existing-domain.org/的不存在的域并显示自定义错误页面:

import 'dart:async';

import 'package:flutter/material.dart';

import 'package:flutter_inappwebview/flutter_inappwebview.dart';

Future main() async {
  runApp(new MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => new _MyAppState();
}

class _MyAppState extends State<MyApp> {

  @override
  void initState() {
    super.initState();
  }

  @override
  void dispose() {
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: InAppWebViewPage()
    );
  }
}

class InAppWebViewPage extends StatefulWidget {
  @override
  _InAppWebViewPageState createState() => new _InAppWebViewPageState();
}

class _InAppWebViewPageState extends State<InAppWebViewPage> {
  InAppWebViewController webView;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
            title: Text("InAppWebView")
        ),
        body: Container(
            child: Column(children: <Widget>[
              Expanded(
                child: Container(
                  child: InAppWebView(
                    initialUrl: "http://not-existing-domain.org/",
                    initialHeaders: {},
                    initialOptions: InAppWebViewWidgetOptions(
                        inAppWebViewOptions: InAppWebViewOptions(
                          debuggingEnabled: true,
                        ),
                    ),
                    onWebViewCreated: (InAppWebViewController controller) {
                      webView = controller;
                    },
                    onLoadStart: (InAppWebViewController controller, String url) {

                    },
                    onLoadStop: (InAppWebViewController controller, String url) {

                    },
                    onLoadError: (InAppWebViewController controller, String url, int code, String message) async {
                      print("error $url: $code, $message");

                      var tRexHtml = await controller.getTRexRunnerHtml();
                      var tRexCss = await controller.getTRexRunnerCss();

                      controller.loadData(data: """
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0,maximum-scale=1.0, user-scalable=no">
    <style>$tRexCss</style>
  </head>
  <body>
    $tRexHtml
    <p>
      URL $url failed to load.
    </p>
    <p>
      Error: $code, $message
    </p>
  </body>
</html>
                  """);
                    },
                    onLoadHttpError: (InAppWebViewController controller, String url, int statusCode, String description) async {
                      print("HTTP error $url: $statusCode, $description");
                    },
                  ),
                ),
              ),
            ]))
    );
  }
}

结果是:

此示例直接加载html源,但是您可以从资产文件夹或url加载html文件。

只是为了好玩:我的插件包含Google Chrome t-rex游戏的javascript和CSS代码!

答案 1 :(得分:0)

不确定我们是否可以修改从Webview本身显示的实际消息,但是我已经使用了一种解决方法。

只要出现错误,就可以使用堆栈小部件并在单独的小部件中显示自定义消息。下面是示例代码。

     Stack(
          children: [
            if (!controller.isError)
              WebView(
                javascriptMode: JavascriptMode.unrestricted,
                initialUrl: "https://some-random-url.com",
                onPageFinished: controller.onLoaded,
                onWebResourceError: controller.onError,
              ),
            if (controller.isLoading)
              Center(
                child: CircularProgressIndicator(
                  valueColor: AlwaysStoppedAnimation<Color>(Colors.black),
                ),
              ),
            if (controller.isError)
              Center(
                child: Padding(
                  padding: const EdgeInsets.only(left: 8.0, right: 8.0),
                  child: Text(
                    text: "Something went wrong, please try again", 
                  ),
                ),
              )
          ],
        ),

您看到的Controller对象是我用于状态管理的GetX控制器,您可以随意使用任何对象。主要动作元素是

  1. isError->状态变量,用于监视是否发生错误。

  2. WebView.onWebResourceError->发生特定错误时调用的回调函数。 您可以将函数传递给此函数,并且仅在发生错误时才调用此回调。这样,您便可以将状态变量isError修改为true,这将依次隐藏Web视图并在屏幕中央显示错误消息。

有了这个,您将获得所需的错误处理。

PS:我知道我迟到了这个答案,但我希望其他人觉得它有用。