goback in webview flutter by back button device

后端 未结 1 1382
孤城傲影
孤城傲影 2021-01-16 05:44

I have 4 bottomNavigationBar that each one has a webview. but when tap in a one bottomNavigationBar and select a section in webview page, I can\'t back to previous p

相关标签:
1条回答
  • 2021-01-16 05:59

    You can copy paste run full code below
    You can wrap Scaffold with WillPopScope
    When user click device back button, you can execute WebView Controller goback

    code snippet onwillpop

    @override
      Widget build(BuildContext context) {
        return WillPopScope(
          onWillPop: () => _exitApp(context),
          child: Scaffold(
            appBar: AppBar(
              title: const Text('Flutter WebView example'),
              // This drop down menu demonstrates that Flutter widgets can be shown over the web view.
              actions: <Widget>[
                NavigationControls(_controller.future),
                SampleMenu(_controller.future),
              ],
            ),
    

    code snippet for exit app

    WebViewController controllerGlobal;
    
    Future<bool> _exitApp(BuildContext context) async {
      if (await controllerGlobal.canGoBack()) {
        print("onwill goback");
        controllerGlobal.goBack();
      } else {
        Scaffold.of(context).showSnackBar(
          const SnackBar(content: Text("No back history item")),
        );
        return Future.value(false);
      }
    }
    

    working demo

    full code

    import 'dart:async';
    import 'dart:convert';
    import 'package:flutter/material.dart';
    import 'package:webview_flutter/webview_flutter.dart';
    
    void main() => runApp(MaterialApp(home: WebViewExample()));
    
    const String kNavigationExamplePage = '''
    <!DOCTYPE html><html>
    <head><title>Navigation Delegate Example</title></head>
    <body>
    <p>
    The navigation delegate is set to block navigation to the youtube website.
    </p>
    <ul>
    <ul><a href="https://www.youtube.com/">https://www.youtube.com/</a></ul>
    <ul><a href="https://www.google.com/">https://www.google.com/</a></ul>
    <ul><a href="https://www.google.com/">https://nodejs.org/en</a></ul>
    </ul>
    </body>
    </html>
    ''';
    
    class WebViewExample extends StatefulWidget {
      @override
      _WebViewExampleState createState() => _WebViewExampleState();
    }
    
    WebViewController controllerGlobal;
    
    Future<bool> _exitApp(BuildContext context) async {
      if (await controllerGlobal.canGoBack()) {
        print("onwill goback");
        controllerGlobal.goBack();
      } else {
        Scaffold.of(context).showSnackBar(
          const SnackBar(content: Text("No back history item")),
        );
        return Future.value(false);
      }
    }
    
    class _WebViewExampleState extends State<WebViewExample> {
      final Completer<WebViewController> _controller =
      Completer<WebViewController>();
    
      @override
      Widget build(BuildContext context) {
        return WillPopScope(
          onWillPop: () => _exitApp(context),
          child: Scaffold(
            appBar: AppBar(
              title: const Text('Flutter WebView example'),
              // This drop down menu demonstrates that Flutter widgets can be shown over the web view.
              actions: <Widget>[
                NavigationControls(_controller.future),
                SampleMenu(_controller.future),
              ],
            ),
            // We're using a Builder here so we have a context that is below the Scaffold
            // to allow calling Scaffold.of(context) so we can show a snackbar.
            body: Builder(builder: (BuildContext context) {
              return WebView(
                initialUrl: 'https://flutter.dev',
                javascriptMode: JavascriptMode.unrestricted,
                onWebViewCreated: (WebViewController webViewController) {
                  _controller.complete(webViewController);
                },
                // TODO(iskakaushik): Remove this when collection literals makes it to stable.
                // ignore: prefer_collection_literals
                javascriptChannels: <JavascriptChannel>[
                  _toasterJavascriptChannel(context),
                ].toSet(),
                navigationDelegate: (NavigationRequest request) {
                  if (request.url.startsWith('https://www.youtube.com/')) {
                    print('blocking navigation to $request}');
                    return NavigationDecision.prevent;
                  }
                  if (request.url.startsWith('https://flutter.dev/docs')) {
                    print('blocking navigation to $request}');
                    return NavigationDecision.prevent;
                  }
                  print('allowing navigation to $request');
                  return NavigationDecision.navigate;
                },
                onPageFinished: (String url) {
                  print('Page finished loading: $url');
                },
              );
            }),
            floatingActionButton: favoriteButton(),
          ),
        );
      }
    
      JavascriptChannel _toasterJavascriptChannel(BuildContext context) {
        return JavascriptChannel(
            name: 'Toaster',
            onMessageReceived: (JavascriptMessage message) {
              Scaffold.of(context).showSnackBar(
                SnackBar(content: Text(message.message)),
              );
            });
      }
    
      Widget favoriteButton() {
        return FutureBuilder<WebViewController>(
            future: _controller.future,
            builder: (BuildContext context,
                AsyncSnapshot<WebViewController> controller) {
              if (controller.hasData) {
                return FloatingActionButton(
                  onPressed: () async {
                    final String url = await controller.data.currentUrl();
                    Scaffold.of(context).showSnackBar(
                      SnackBar(content: Text('Favorited $url')),
                    );
                  },
                  child: const Icon(Icons.favorite),
                );
              }
              return Container();
            });
      }
    }
    
    enum MenuOptions {
      showUserAgent,
      listCookies,
      clearCookies,
      addToCache,
      listCache,
      clearCache,
      navigationDelegate,
    }
    
    class SampleMenu extends StatelessWidget {
      SampleMenu(this.controller);
    
      final Future<WebViewController> controller;
      final CookieManager cookieManager = CookieManager();
    
      @override
      Widget build(BuildContext context) {
        return FutureBuilder<WebViewController>(
          future: controller,
          builder:
              (BuildContext context, AsyncSnapshot<WebViewController> controller) {
            return PopupMenuButton<MenuOptions>(
              onSelected: (MenuOptions value) {
                switch (value) {
                  case MenuOptions.showUserAgent:
                    _onShowUserAgent(controller.data, context);
                    break;
                  case MenuOptions.listCookies:
                    _onListCookies(controller.data, context);
                    break;
                  case MenuOptions.clearCookies:
                    _onClearCookies(context);
                    break;
                  case MenuOptions.addToCache:
                    _onAddToCache(controller.data, context);
                    break;
                  case MenuOptions.listCache:
                    _onListCache(controller.data, context);
                    break;
                  case MenuOptions.clearCache:
                    _onClearCache(controller.data, context);
                    break;
                  case MenuOptions.navigationDelegate:
                    _onNavigationDelegateExample(controller.data, context);
                    break;
                }
              },
              itemBuilder: (BuildContext context) => <PopupMenuItem<MenuOptions>>[
                PopupMenuItem<MenuOptions>(
                  value: MenuOptions.showUserAgent,
                  child: const Text('Show user agent'),
                  enabled: controller.hasData,
                ),
                const PopupMenuItem<MenuOptions>(
                  value: MenuOptions.listCookies,
                  child: Text('List cookies'),
                ),
                const PopupMenuItem<MenuOptions>(
                  value: MenuOptions.clearCookies,
                  child: Text('Clear cookies'),
                ),
                const PopupMenuItem<MenuOptions>(
                  value: MenuOptions.addToCache,
                  child: Text('Add to cache'),
                ),
                const PopupMenuItem<MenuOptions>(
                  value: MenuOptions.listCache,
                  child: Text('List cache'),
                ),
                const PopupMenuItem<MenuOptions>(
                  value: MenuOptions.clearCache,
                  child: Text('Clear cache'),
                ),
                const PopupMenuItem<MenuOptions>(
                  value: MenuOptions.navigationDelegate,
                  child: Text('Navigation Delegate example'),
                ),
              ],
            );
          },
        );
      }
    
      void _onShowUserAgent(
          WebViewController controller, BuildContext context) async {
        // Send a message with the user agent string to the Toaster JavaScript channel we registered
        // with the WebView.
        controller.evaluateJavascript(
            'Toaster.postMessage("User Agent: " + navigator.userAgent);');
      }
    
      void _onListCookies(
          WebViewController controller, BuildContext context) async {
        final String cookies =
        await controller.evaluateJavascript('document.cookie');
        Scaffold.of(context).showSnackBar(SnackBar(
          content: Column(
            mainAxisAlignment: MainAxisAlignment.end,
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
              const Text('Cookies:'),
              _getCookieList(cookies),
            ],
          ),
        ));
      }
    
      void _onAddToCache(WebViewController controller, BuildContext context) async {
        await controller.evaluateJavascript(
            'caches.open("test_caches_entry"); localStorage["test_localStorage"] = "dummy_entry";');
        Scaffold.of(context).showSnackBar(const SnackBar(
          content: Text('Added a test entry to cache.'),
        ));
      }
    
      void _onListCache(WebViewController controller, BuildContext context) async {
        await controller.evaluateJavascript('caches.keys()'
            '.then((cacheKeys) => JSON.stringify({"cacheKeys" : cacheKeys, "localStorage" : localStorage}))'
            '.then((caches) => Toaster.postMessage(caches))');
      }
    
      void _onClearCache(WebViewController controller, BuildContext context) async {
        await controller.clearCache();
        Scaffold.of(context).showSnackBar(const SnackBar(
          content: Text("Cache cleared."),
        ));
      }
    
      void _onClearCookies(BuildContext context) async {
        final bool hadCookies = await cookieManager.clearCookies();
        String message = 'There were cookies. Now, they are gone!';
        if (!hadCookies) {
          message = 'There are no cookies.';
        }
        Scaffold.of(context).showSnackBar(SnackBar(
          content: Text(message),
        ));
      }
    
      void _onNavigationDelegateExample(
          WebViewController controller, BuildContext context) async {
        final String contentBase64 =
        base64Encode(const Utf8Encoder().convert(kNavigationExamplePage));
        controller.loadUrl('data:text/html;base64,$contentBase64');
      }
    
      Widget _getCookieList(String cookies) {
        if (cookies == null || cookies == '""') {
          return Container();
        }
        final List<String> cookieList = cookies.split(';');
        final Iterable<Text> cookieWidgets =
        cookieList.map((String cookie) => Text(cookie));
        return Column(
          mainAxisAlignment: MainAxisAlignment.end,
          mainAxisSize: MainAxisSize.min,
          children: cookieWidgets.toList(),
        );
      }
    }
    
    
    
    class NavigationControls extends StatelessWidget {
      const NavigationControls(this._webViewControllerFuture)
          : assert(_webViewControllerFuture != null);
    
      final Future<WebViewController> _webViewControllerFuture;
    
      @override
      Widget build(BuildContext context) {
        return FutureBuilder<WebViewController>(
          future: _webViewControllerFuture,
          builder:
              (BuildContext context, AsyncSnapshot<WebViewController> snapshot) {
            final bool webViewReady =
                snapshot.connectionState == ConnectionState.done;
            final WebViewController controller = snapshot.data;
            controllerGlobal = controller;
    
            return Row(
              children: <Widget>[
                IconButton(
                  icon: const Icon(Icons.arrow_back_ios),
                  onPressed: !webViewReady
                      ? null
                      : () async {
                    if (await controller.canGoBack()) {
                      controller.goBack();
                    } else {
                      Scaffold.of(context).showSnackBar(
                        const SnackBar(content: Text("No back history item")),
                      );
                      return;
                    }
                  },
                ),
                IconButton(
                  icon: const Icon(Icons.arrow_forward_ios),
                  onPressed: !webViewReady
                      ? null
                      : () async {
                    if (await controller.canGoForward()) {
                      controller.goForward();
                    } else {
                      Scaffold.of(context).showSnackBar(
                        const SnackBar(
                            content: Text("No forward history item")),
                      );
                      return;
                    }
                  },
                ),
                IconButton(
                  icon: const Icon(Icons.replay),
                  onPressed: !webViewReady
                      ? null
                      : () {
                    controller.reload();
                  },
                ),
              ],
            );
          },
        );
      }
    }
    
    0 讨论(0)
提交回复
热议问题