1

Hello I am new to flutter but I am somehow created a webview app. Now I want some additional features like show custom page when url not loaded, or when web page not found. I have searched google a lot but not able to find any solution.

My code:

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';

import '../main.dart';

class Outlook extends StatefulWidget {
  const Outlook({Key? key}) : super(key: key);

  @override
  State<Outlook> createState() => _OutlookState();
}

class _OutlookState extends State<Outlook> {
  bool isLoading=true;
  late WebViewController _controller;
  final _key = UniqueKey();
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
          title: const Text("Outlook"),
          backgroundColor: const Color(0xff6200EE),
          centerTitle: true,
      ),
      body: Stack(
        children: <Widget>[
          WebView(
            key: _key,
            initialUrl: "https://outlook.office.com/",
            javascriptMode: JavascriptMode.unrestricted,
            onWebResourceError: (WebResourceError error) {
              _controller.loadUrl("http://connectivitycheck.gstatic.com/generate_204");
            },
            onPageFinished: (finish) {
              setState(() {
                isLoading = false;
              });
            },
          ),
          isLoading ? const Center( child: CircularProgressIndicator(),)
              : Stack(),
        ],
      ),
      drawer: const Navigation(),
    );
  }

}
Aman Singh
  • 41
  • 2

1 Answers1

0

To manage and display a custom error page, you can try my plugin flutter_inappwebview.

Use the InAppWebView.onReceivedError event to handle web page loading errors and the InAppWebView.onReceivedHttpError event to handle HTTP errors. Also, on Android, you should set the InAppWebViewSettings.disableDefaultErrorPage property to true.

Here is an example using the current latest version 6 (6.0.0-beta.18):

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';

Future main() async {
  WidgetsFlutterBinding.ensureInitialized();
  if (!kIsWeb &&
      kDebugMode &&
      defaultTargetPlatform == TargetPlatform.android) {
    await InAppWebViewController.setWebContentsDebuggingEnabled(kDebugMode);
  }
  runApp(const MaterialApp(home: MyApp()));
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final GlobalKey webViewKey = GlobalKey();

  InAppWebViewController? webViewController;

  handleClick(int item) {
    switch (item) {
      case 0:
        webViewController?.loadUrl(
            urlRequest:
                URLRequest(url: WebUri('https://www.notawebsite..com/')));
        break;
      case 1:
        webViewController?.loadUrl(
            urlRequest: URLRequest(url: WebUri('https://google.com/404')));
        break;
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text("Custom Error Page"),
          actions: [
            PopupMenuButton<int>(
              onSelected: (item) => handleClick(item),
              itemBuilder: (context) => [
                const PopupMenuItem<int>(
                    value: 0, child: Text('Test web page loading error')),
                const PopupMenuItem<int>(
                    value: 1, child: Text('Test 404 error')),
              ],
            ),
          ],
        ),
        body: Column(children: <Widget>[
          Expanded(
            child: InAppWebView(
              key: webViewKey,
              initialUrlRequest:
                  URLRequest(url: WebUri('https://github.com/flutter')),
              initialSettings:
                  InAppWebViewSettings(disableDefaultErrorPage: true),
              onWebViewCreated: (controller) {
                webViewController = controller;
              },
              onReceivedHttpError: (controller, request, errorResponse) async {
                // Handle HTTP errors here
                var isForMainFrame = request.isForMainFrame ?? false;
                if (!isForMainFrame) {
                  return;
                }

                final snackBar = SnackBar(
                  content: Text(
                      'HTTP error for URL: ${request.url} with Status: ${errorResponse.statusCode} ${errorResponse.reasonPhrase ?? ''}'),
                );
                ScaffoldMessenger.of(context).showSnackBar(snackBar);
              },
              onReceivedError: (controller, request, error) async {
                // Handle web page loading errors here
                var isForMainFrame = request.isForMainFrame ?? false;
                if (!isForMainFrame ||
                    (!kIsWeb &&
                        defaultTargetPlatform == TargetPlatform.iOS &&
                        error.type == WebResourceErrorType.CANCELLED)) {
                  return;
                }

                var errorUrl = request.url;
                controller.loadData(data: """
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <style>
    ${await InAppWebViewController.tRexRunnerCss}
    </style>
    <style>
    .interstitial-wrapper {
        box-sizing: border-box;
        font-size: 1em;
        line-height: 1.6em;
        margin: 0 auto 0;
        max-width: 600px;
        width: 100%;
    }
    </style>
</head>
<body>
    ${await InAppWebViewController.tRexRunnerHtml}
    <div class="interstitial-wrapper">
      <h1>Website not available</h1>
      <p>Could not load web pages at <strong>$errorUrl</strong> because:</p>
      <p>${error.description}</p>
    </div>
</body>
    """, baseUrl: errorUrl, historyUrl: errorUrl);
              },
            ),
          ),
        ]));
  }
}

Full project code example available at https://github.com/pichillilorenzo/flutter_inappwebview_examples/tree/main/custom_error_page

Android example iOS example

Lorenzo Pichilli
  • 2,896
  • 1
  • 27
  • 50
  • How To Set Cookies In WebView as I want the user to not logout for 1 week. – Aman Singh Dec 02 '22 at 14:59
  • To manage cookies, use the [CookieManager](https://inappwebview.dev/docs/cookie-manager) class – Lorenzo Pichilli Dec 02 '22 at 15:44
  • Man your plugin is awesome but after the update your old codes are not working, please update them I have tried all the github examples and many of them showing error. In the above code initialSettings is not defined and many other variable please update and post here. – Aman Singh Dec 02 '22 at 16:46
  • Thanks! As written in the answer, the code example is using plugin version 6.0.0-beta.18! Check the pubspec.yaml of the repository of the project example that I linked there – Lorenzo Pichilli Dec 02 '22 at 20:32
  • Thank you, can you plz tell me how can i show circularprogressindicator during loading webview? Also when I am using drawer it is not doing anything even after creating key – Aman Singh Dec 03 '22 at 06:12