Prototype
Prototype

Reputation: 568

How to fix WillPopScope() not working for me

I created two pages one is login and main page but i want close app from main page i am using Willpopscope but it is not working for me i have tried all things but the onwillpop method is not calling please help me thank you.

class main_page extends StatelessWidget {
@override
Widget build(BuildContext context) {
  return MaterialApp(
  theme: ThemeData(primarySwatch: Colors.amber),
  home: my_page(),
);
}
}

class my_page extends StatefulWidget {
@override
_my_pageState createState() => _my_pageState();
}

class _my_pageState extends State<my_page> {
 @override
void initState() {
check_login();
 super.initState();
}

Future check_login() async {
SharedPreferences preferences = await SharedPreferences.getInstance();
if (preferences.getBool("islogin") == false)
  setState(() {
    Navigator.of(context).push(MaterialPageRoute(
      builder: (context) => MyApp(),
    ));
  });
}

@override
 Widget build(BuildContext context) {
return WillPopScope(
  onWillPop: () async=>false,
  child: Scaffold(
    appBar: new AppBar(
      title: Text(
        "Home",
        style: new TextStyle(color: Colors.white),
      ),
      actions: <Widget>[
        FlatButton(
            onPressed: () async {
              SharedPreferences sharedPreferences =
                  await SharedPreferences.getInstance();

              setState(() {
                sharedPreferences.setBool("islogin", false);
                Navigator.of(context).push(MaterialPageRoute(
                  builder: (context) => main_page(),
                ));
              });
            },
            child: Text(
              "Logout",
              style: TextStyle(color: Colors.white, fontSize: 16.0),
            ))
      ],
    ),
  ),
);
}
}

I am also using Shredprefrences but i think it does not matter i want close app from my main_page please help me for this Thank you.

Upvotes: 10

Views: 29692

Answers (6)

I was struggling with this problem, none of answers helped but finally I found the correct answer in BackButton widget source code.

When we use WillPopScope on top of our widget, we should use maybePop instead of pop method that forces the Navigator to pop the last pushed page in order to let the WillPopScope widget decides the next action.

Navigator.maybePop(context);

Upvotes: 16

Ahmad hassan
Ahmad hassan

Reputation: 1009

I resolved this error as in my case I have a parent screen and in that, I have PageView. I was trying to call WillPopScope in one of my PageView and then I realized my parent have WillPopScope too.

That is why it is not calling WillPopScope of PageView

Upvotes: 0

D.Algorithm
D.Algorithm

Reputation: 1

don't use on Scaffold(), wrap your MaterialApp as in the example

bool allowed = false;
return WillPopScope(
  onWillPop: () async {
    print('MJD POP TRYING TO GET BACK from login Page');
    return Future.value(allowed);
  },
  child: MaterialApp(
    title: 'Your App Title',
    theme: ThemeData(
      primarySwatch: Colors.blue,
    ),
    home: const MyLoginPage(title: 'Login Page'),
  ),
);

Upvotes: -5

Sagar Acharya
Sagar Acharya

Reputation: 3767

Just check out this answer and let me know if it works:

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:flutter/services.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(primarySwatch: Colors.amber),
      home: SecondPage(),
    );
  }
}

class LoginPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        child: Center(
            child: RaisedButton(
          child: Text('Move to second page after Login'),
          onPressed: () async {
            SharedPreferences preferences =
                await SharedPreferences.getInstance();

            preferences.setBool("islogin", true);
            // this will remove the login page after routing to the second page and then the stack will have only one page that is second page.
           // so later you can use the willpopscape 
            Navigator.pushAndRemoveUntil(
                context,
                MaterialPageRoute(builder: (context) => SecondPage()),
                ModalRoute.withName("/Home"));
          },
        )),
      ),
    );
  }
}

class SecondPage extends StatefulWidget {
  @override
  _SecondPageState createState() => _SecondPageState();
}

class _SecondPageState extends State<SecondPage> {
  @override
  void initState() {
    check_login();
    
    super.initState();
  }

  Future check_login() async {
    SharedPreferences preferences = await SharedPreferences.getInstance();
    if (preferences.getBool("islogin") == null)

    //This above if statement will check if the parameter islogin is null then redirect to the login screeen
    // else if the value is not null then i will not enter the if statement
      setState(() {
        Navigator.of(context).push(MaterialPageRoute(
          builder: (context) => LoginPage(),
        ));
      });
  }

  Future<bool> _onWillPop() async {

    // This dialog will exit your app on saying yes
    return (await showDialog(
          context: context,
          builder: (context) => new AlertDialog(
            title: new Text('Are you sure?'),
            content: new Text('Do you want to exit an App'),
            actions: <Widget>[
              new FlatButton(
                onPressed: () => Navigator.of(context).pop(false),
                child: new Text('No'),
              ),
              new FlatButton(
                onPressed: () => Navigator.of(context).pop(true),
                child: new Text('Yes'),
              ),
            ],
          ),
        )) ??
        false;
  }

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: _onWillPop,
      child: Scaffold(
        appBar: new AppBar(
          title: Text(
            "Home",
            style: new TextStyle(color: Colors.white),
          ),
          actions: <Widget>[
            FlatButton(
                onPressed: () async {
                   SystemNavigator.pop();
                },
                child: Text(
                  "Logout",
                  style: TextStyle(color: Colors.white, fontSize: 16.0),
                ))
          ],
        ),
      ),
    );
  }
}

Upvotes: 5

Prototype
Prototype

Reputation: 568

Here is answer example_page code

class exmp extends StatefulWidget {
@override
_exmpState createState() => _exmpState();
}

class _exmpState extends State<exmp> {
@override
Widget build(BuildContext context) {
return Scaffold(
  appBar: AppBar(
    title: Text("example"),
  ),
  body: Column(
    children: <Widget>[
      Center(
        child: RaisedButton(onPressed: () {
          Navigator.of(context).pushAndRemoveUntil(
              MaterialPageRoute(
                builder: (context) => my_example(),
              ),
              (route) => false);
        }),
      )
    ],
  ),
);
}
}

And this is my second page my_example

class my_example extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
  return MaterialApp(
  theme: ThemeData(primarySwatch: Colors.amber),
  home: my_examp(),
);
 }
}

 class my_examp extends StatefulWidget {
  @override
  _my_exampState createState() => _my_exampState();
 }

class _my_exampState extends State<my_examp> {
Future<bool> onbackpress() async{
return true;
}

@override
Widget build(BuildContext context) {
return WillPopScope(
  onWillPop: onbackpress,
  child: Scaffold(
    appBar: AppBar(
      title: Text("my_eaxmple"),
    ),
  ),
);
}
}

The problem was i am pushing another page from my main page but i forget to remove first page for that i used the Navigator.of(context).pushAndRemoveUntil( MaterialPageRoute(builder: (context) => my_example()(route) => false); to remove the main page before navigate to another page

Upvotes: 3

Deepak Ror
Deepak Ror

Reputation: 2234

This is how you should use

Future<bool> _willPopCallback() async {
    // await Show dialog of exit or what you want
    // then
    return true; //  
}


//then use in the build like
WillPopScope(child: new Scaffold(), onWillPop: _willPopCallback)

Upvotes: 0

Related Questions