如何在Flutter中成功加载WebView之前显示本地图像?

时间:2019-07-29 05:24:10

标签: flutter webview

在Flutter中,我想在加载Web视图之前显示本地图像。如果用户没有打开wifi,则会显示图片,而不是空白的白屏(ios)或错误消息,提示无法连接到该网页(android)。

我正在为此应用使用官方的webview_flutter软件包。

下面是我尝试过的代码,但是它可以在ios上运行,但不能在android上运行。在Android中,当我关闭wifi并启动应用程序时,会显示一条错误消息,其中显示了webview链接。

Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: <Widget>[
          WebView(
            key: _key,
            initialUrl: _url,
            javascriptMode: JavascriptMode.unrestricted,
            onWebViewCreated: (webViewCreate) {
              _controller.complete(webViewCreate);
            },
            onPageFinished: (finish) {
              setState(() {
                _isLoadingPage = false;
              });
             },
          ),
          _isLoadingPage
            ? Container(
              decoration: BoxDecoration(
                image: DecorationImage(
                  image: AssetImage('assets/images/fail.png'),
                  fit: BoxFit.fill,
                ),
              ),
            )
            : Container(
              color: Colors.transparent,
            ),
        ],
      ),
    );
  }

3 个答案:

答案 0 :(得分:0)

  

使用不透明度小部件使其不可见,并在完成时显示它。

Opacity(opacity: _isLoadingPage?0:1, child: WebView(
          key: _key,
          initialUrl: _url,
          javascriptMode: JavascriptMode.unrestricted,
          onWebViewCreated: (webViewCreate) {
            _controller.complete(webViewCreate);
          },
          onPageFinished: (finish) {
            setState(() {
              _isLoadingPage = false;
            });
          },
        ),)

答案 1 :(得分:0)

您可以使用IndexedStack,并在使用onPageFinished加载Webview之后在小部件之间切换。

int _page = 1;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: IndexedStack(
        index: _page,
        children: <Widget>[
          WebView(
            initialUrl: 'https://www.cnet.com/news/',
            onPageFinished: (_) {
              setState(() {
                _page = 0;
              });
            },
          ),
          Container(
            child: Center(
              child: CircularProgressIndicator(),
            ),
          ),
        ],
      ),
    );
  }

答案 2 :(得分:0)

您可以使用我的插件flutter_inappwebview,该插件有很多事件,包括在WebView加载URL(onLoadError事件)时管理错误的事件(例如net :: ERR_ADDRESS_UNREACHABLE)和当它收到HTTP错误,例如403、404等(onLoadHttpError事件)时。

您可以通过订阅连接插件公开的流来使用connectivity插件来监听网络状态更改。

此外,您可以使用IndexedStack并在使用onLoadStop加载WebView之后在小部件之间切换。

完整示例:

import 'dart:async';
import 'dart:io';

import 'package:flutter/material.dart';

import 'package:connectivity/connectivity.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;
  int _page = 2;
  bool _loadError = false;
  StreamSubscription<ConnectivityResult> subscription;

  @override
  initState() {
    super.initState();
    subscription = Connectivity().onConnectivityChanged.listen((ConnectivityResult result) {
      if (result != ConnectivityResult.none && webView != null) {
        print("reload");
        _loadError = false;
        webView.reload();
      }
    });
  }

  @override
  dispose() {
    super.dispose();
    subscription.cancel();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
            title: Text("InAppWebView")
        ),
        body: IndexedStack(
          index: _page,
          children: <Widget>[
            InAppWebView(
              initialUrl: "https://flutter.dev",
              initialHeaders: {},
              initialOptions: InAppWebViewWidgetOptions(
                  inAppWebViewOptions: InAppWebViewOptions(
                    clearCache: true,
                    debuggingEnabled: true,
                  ),
              ),
              onWebViewCreated: (InAppWebViewController controller) {
                webView = controller;
              },
              onLoadStart: (InAppWebViewController controller, String url) {

              },
              onLoadStop: (InAppWebViewController controller, String url) {
                print(url);
                setState(() {
                  if (!_loadError) {
                    _page = 0;
                  } else {
                    _page = 1;
                  }
                });
              },
              onLoadError: (InAppWebViewController controller, String url, int code, String message) async {
                print("error $url: $code, $message");
                _loadError = true;
              },
              onLoadHttpError: (InAppWebViewController controller, String url, int statusCode, String description) async {
                print("HTTP error $url: $statusCode, $description");
              },
            ),
            (Platform.isAndroid) ? Container(
                child: Text("My custom error message"),
            ) : Container(
                decoration: BoxDecoration(
                  image: DecorationImage(
                    image: AssetImage('assets/images/fail.png'),
                    fit: BoxFit.fill,
                  ),
                )
            ),
            Container(
              decoration: BoxDecoration(
                image: DecorationImage(
                  image: AssetImage('assets/images/loading.jpg'),
                  fit: BoxFit.fill,
                ),
              )
            )
          ],
        ),
    );
  }
}