How to Handle Webview Back Button Event in Flutter?

Last updated Sep 08, 2021

In this Flutter example we will learn how to handle back button event when we load web pages inside flutter webview. We know that webview will render the webpages inside native mobile applications. In flutter to load web pages we will use webview_flutter plugin. When we load webpages and while tap on internal links, it will load we pages on the same view, on this current page if we press device back button we required to load previous web page but it will close the current screen. to overcome this issue we will WillPopScope() widget to handle device back button events.

For this back button events we will show alert dialog when user press back button if there is no other previous web pages to navigate inside webview.

In this example we used provider plugin check the state of the device back button event. To read more about Change Notifier provider

 

Let's get started

 

Download Source code

 

Step 1: Create Flutter application

Step 2: Add required plugins inside pubspec.yaml file

Step 3: Create a Change Notifier class to manage the state of the back button click event.

import 'package:flutter/material.dart';

class BackEventNotifier extends ChangeNotifier{

  bool isback=true;
  bool get isBack => isback;
  void add(bool value) {
    isback=value;
    notifyListeners();
  }
}

 

Step 4: Create a webview widget to load web pages.

class Webpage extends StatelessWidget{
  late WebViewController _controll;

  GlobalKey_globalKey=GlobalKey();
  @override
  Widget build(BuildContext context) {

    return WillPopScope(
      onWillPop: _onBack,
      child: Scaffold(
        key: _globalKey,
        appBar: AppBar(title: Text( 'Webview Back Button '),),
        body: WebView(
          initialUrl: 'https://flutter.dev/',
          javascriptMode: JavascriptMode.unrestricted,
          onWebViewCreated: ( webViewController) {
            _controll=webViewController;


          },
          onProgress: (int progress) {

            print("WebView is loading (progress : $progress%)");
          },
          javascriptChannels: {
            _toasterJavascriptChannel(context),
          },
          navigationDelegate: (NavigationRequest request) {
            print('allowing navigation to $request');
            return NavigationDecision.navigate;
          },
          onPageStarted: (String url) {
            print('Page started loading: $url');
          },
          onPageFinished: (String url) {
            print('Page finished loading: $url');
          },
          gestureNavigationEnabled: true,
        ),
      ),
    );


  }
  JavascriptChannel _toasterJavascriptChannel(BuildContext context) {
    return JavascriptChannel(
        name: 'Toaster',
        onMessageReceived: (JavascriptMessage message) {
          // ignore: deprecated_member_use
          Scaffold.of(context).showSnackBar(
            SnackBar(content: Text(message.message)),
          );
        });
  }
}

 

Step 5: Create a Future function to pass the value to onWillPop() method of WillPopScope widget

Future _onBack() async {

  bool goBack;

  var value = await _controll.canGoBack();  // check webview can go back

  if (value) {

    _controll.goBack(); // perform webview back operation

    return false;

  } else {
    late BackEventNotifier _notifier;
   await showDialog(

      context: _globalKey.currentState!.context,

      builder: (context) => Consumer(
     builder: (context, event, child) {
       _notifier=event;
       return new AlertDialog(

         title: new Text(
             'Confirmation ', style: TextStyle(color: Colors.purple)),

         content: new Text('Do you want exit app ? '),

         actions: [

           new TextButton(

             onPressed: () {
               Navigator.of(context).pop(false);
               event.add(false);
             },

             child: new Text("No"), // No

           ),
           new TextButton(
             onPressed: () {
               Navigator.of(context).pop();
               event.add(true);
             },
             child: new Text("Yes"), // Yes
           ),
         ],
       );
     }
     )



    );

    //Navigator.pop(_globalKey.currentState!.context);
 print("_notifier.isBack ${_notifier.isBack}");
    return _notifier.isBack;
  }
}

 

Step 6: To handle the Change Notifier listeners we will load widget inside Providers

runApp(
    ChangeNotifierProvider(
  create: (context) => BackEventNotifier(),
  child:  MyApp(),
));

 

Step 7: Run application

Flutter webview back button event

 

Complete code:

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

import 'backevent_notifier.dart';
void main() {

  runApp(
      ChangeNotifierProvider(
    create: (context) => BackEventNotifier(),
    child:  MyApp(),
  ));
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Webpage(),
    );
  }
}

class Webpage extends StatelessWidget{
  late WebViewController _controll;

  GlobalKey_globalKey=GlobalKey();
  @override
  Widget build(BuildContext context) {

    return WillPopScope(
      onWillPop: _onBack,
      child: Scaffold(
        key: _globalKey,
        appBar: AppBar(title: Text( 'Webview Back Button '),),
        body: WebView(
          initialUrl: 'https://flutter.dev/',
          javascriptMode: JavascriptMode.unrestricted,
          onWebViewCreated: ( webViewController) {
            _controll=webViewController;


          },
          onProgress: (int progress) {

            print("WebView is loading (progress : $progress%)");
          },
          javascriptChannels: {
            _toasterJavascriptChannel(context),
          },
          navigationDelegate: (NavigationRequest request) {
            print('allowing navigation to $request');
            return NavigationDecision.navigate;
          },
          onPageStarted: (String url) {
            print('Page started loading: $url');
          },
          onPageFinished: (String url) {
            print('Page finished loading: $url');
          },
          gestureNavigationEnabled: true,
        ),
      ),
    );


  }
  JavascriptChannel _toasterJavascriptChannel(BuildContext context) {
    return JavascriptChannel(
        name: 'Toaster',
        onMessageReceived: (JavascriptMessage message) {
          // ignore: deprecated_member_use
          Scaffold.of(context).showSnackBar(
            SnackBar(content: Text(message.message)),
          );
        });
  }

  Future _onBack() async {

    bool goBack;

    var value = await _controll.canGoBack();  // check webview can go back

    if (value) {

      _controll.goBack(); // perform webview back operation

      return false;

    } else {
      late BackEventNotifier _notifier;
     await showDialog(

        context: _globalKey.currentState!.context,

        builder: (context) => Consumer(
       builder: (context, event, child) {
         _notifier=event;
         return new AlertDialog(

           title: new Text(
               'Confirmation ', style: TextStyle(color: Colors.purple)),

           content: new Text('Do you want exit app ? '),

           actions: [

             new TextButton(

               onPressed: () {
                 Navigator.of(context).pop(false);
                 event.add(false);
               },

               child: new Text("No"), // No

             ),
             new TextButton(
               onPressed: () {
                 Navigator.of(context).pop();
                 event.add(true);
               },
               child: new Text("Yes"), // Yes
             ),
           ],
         );
       }
       )



      );

      //Navigator.pop(_globalKey.currentState!.context);
   print("_notifier.isBack ${_notifier.isBack}");
      return _notifier.isBack;
    }
  }

}

 

Conclusion: In this flutter example we covered how to show alert dialog on back button press and handle the webview pages on back button events.

 

Article Contributed By :
https://www.rrtutors.com/site_assets/profile/assets/img/avataaars.svg

345 Views