Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to display a local image before webview is successfully loaded in Flutter?

In Flutter, I would like to display a local image before my webview is loaded. In case the user hasn't turn on their wifi, an image will be shown instead of a blank white screen(ios) or an error message saying cannot connect to said webpage(android).

I am using the official webview_flutter package for this app.

Below is the code that I've tried, but it works on ios but doesn't work on android. In Android, when I turned off the wifi and launch the app, an error message which displays the webview link is shown.

Edit: Does not change from image to webview after wifi is connected and pressed the reload button.

final webViewKey1 = GlobalKey<WebViewContainerState>();
var _url = 'http://www.google.com';
final _key = UniqueKey();
bool _isLoadingPage;

class WebViewPage extends StatefulWidget {
  @override
  WebViewPageState createState() => WebViewPageState();
}

class WebViewPageState extends State<WebViewPage> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Screen 1'),
        leading: IconButton(
          icon: Icon(Icons.menu),
          onPressed: (){
            Scaffold.of(context).openDrawer();
          },
        ),
        actions: <Widget>[
          IconButton(
            icon: Icon(Icons.refresh), 
            color: Colors.white,
            onPressed: () {
              webViewKey1.currentState?.reloadWebView();
            },
          ),
        ]
      ),
      body: 
          WebViewContainer(key: webViewKey1),   
    );
  }
}

class WebViewContainer extends StatefulWidget {
  WebViewContainer({Key key}) : super(key: key);

  @override
  WebViewContainerState createState() => WebViewContainerState();
}

class WebViewContainerState extends State<WebViewContainer> {
  WebViewController _webViewController;

  void initState() {
    super.initState();
    _isLoadingPage = true;
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
        children: <Widget>[
          Opacity(opacity: _isLoadingPage?0:1, child: WebView(
            key: _key,
            initialUrl: _url,
            javascriptMode: JavascriptMode.unrestricted,
            onWebViewCreated: (controller) {
              _webViewController = controller;
            },
            onPageFinished: (finish) {
              setState(() {
                _isLoadingPage = false;
              });
            },
          ),
          ),
          _isLoadingPage
            ? Container(
              decoration: BoxDecoration(
                image: DecorationImage(
                  image: AssetImage('assets/images/fail.png'),
                  fit: BoxFit.fill,
                ),
              ),
            )
            : Container(
              color: Colors.transparent,
            ),
        ],
      );
  }

  void reloadWebView() {
    _webViewController?.reload();
  }
}
like image 947
imgingerbear Avatar asked Dec 04 '25 08:12

imgingerbear


1 Answers

Use opacity widget to make it invisible and on completion show it.

Opacity(opacity: _isLoadingPage?0:1, child: WebView(
          key: _key,
          initialUrl: _url,
          javascriptMode: JavascriptMode.unrestricted,
          onWebViewCreated: (webViewCreate) {
            _controller.complete(webViewCreate);
          },
          onPageFinished: (finish) {
            setState(() {
              _isLoadingPage = false;
            });
          },
        ),)
like image 156
Zulfiqar Avatar answered Dec 07 '25 01:12

Zulfiqar



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!