Search code examples
flutterwebview

WillpopScope is misbehaving in flutter webview


update: check this onwillpop method. and tell what changes can i do.

onWillPop: () async {
        showDialog(
            context: context,
            barrierDismissible: false,
            builder: (BuildContext context) {
              return AlertDialog(
                title: Text("Xác nhận thoát"),
                content: Text("Bạn có chắc bạn muốn thoát?"),
                actions: <Widget>[
                  TextButton(
                    child: Text("VÂNG"),
                    onPressed: () {
                      SystemNavigator.pop();
                    },
                  ),
                  TextButton(
                    child: Text("KHÔNG"),
                    onPressed: () {
                      Navigator.of(context).pop();
                    },
                  )
                ],
              );
            });
        return Future.value(true);
      },

Whenever i am a webpage, and browse site, the back button functionality doesn't works properly, When i press back it opens willpopscope instead it should do Back (just like web browsing)

@override
  Widget build(BuildContext context) {
    WebViewController _controller;

    final Completer<WebViewController> _controllerCompleter =
        Completer<WebViewController>();
    return WillPopScope(
      child: netState
          ? Scaffold(
              body: Padding(
                padding: EdgeInsets.only(top: 32),
                child: WebView(
                  initialUrl: widget.homeURL,
                  zoomEnabled: false,
                  userAgent: 'random',
                  javascriptMode: JavascriptMode.unrestricted,
                  onWebViewCreated: (WebViewController webViewController) {
                    _controllerCompleter.future
                        .then((value) => _controller = value);
                    _controllerCompleter.complete(webViewController);
                  },
                  navigationDelegate: (NavigationRequest request) async {
                    if (request.url.startsWith(widget.homeURL) ||
                        request.url.contains("https://test-payment.momo.vn/") ||
                        request.url.contains("https://payment.momo.vn/") ||
                        request.url.startsWith(
                            "momo://app?action=payWithAppToken&amount=") ||
                        request.url.contains("google.com") ||
                        request.url.contains("facebook.com")) {
                      return NavigationDecision.navigate;
                    } else {
                      return _launchURL(request.url);
                    }
                  },
                ),
              ),

Solution

  • In the new version of flutter WillPopScope was deprecated and PopScope should be used instead. Here's an example of how you should use it

    @override
        Widget build(BuildContext context) {
          return PopScope(
           canPop: false,
           onPopInvoked: (bool didPop) async {
              if (didPop) return;
              await _canPop();
             },
             child: ...
          )}
    

    Function _canPop()

    Future<void> _canPop() async {
        final NavigatorState navigator = Navigator.of(context);
        if (await _controller.canGoBack()) {
          _controller.goBack();
        } else {
          navigator.pop();
        }
      }
    

    Edit:

    In Flutter stable version 3.24.0 onPopInvokedWithResult was introduced and replaced onPopInvoked. Here is the updated code

    @override
        Widget build(BuildContext context) {
          return PopScope(
           canPop: false,
           onPopInvokedWithResult: (bool didPop, _) async {
              if (didPop) return;
              await _canPop();
             },
             child: ...
          )}
    

    the canPop() function remains the same