0

I am working on an flutter application where it has more than 5 screens, I want to handle the back button of android, for example, when I logged in on app, it display the dashboard screen, so when I move to profile and then move to history screen, and when I click on back button on history screen it should navigate to profile screen, because the last screen I visited before history screen is profile, but it display the first screen which login screen.

I found the solution which works like when I click on back button it close the app.

Update:

My screens are navigating from drawer and from bottom navigation, there is only login screen where i use login button and calling dashboard screen onpressed function, other than this there is no button on any screen which navigate to other screens. here is the code for drawer and bottom navigation.

this is line of code i am using on login button

 Navigator.push(
              context, new MaterialPageRoute(builder: (context) => Employee()));

drawer and bottom navigation code: Code:

class Employee extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: new ThemeData(
        primaryColor: Colors.blue
      ),
      home: EmployeeNavigation(),
    );
  }
}
  int _selectedTab = 0;
  final _pageOptions = [
    EmployeeDashboard(),
    location(),
    Profile()
  ];

  String getname="";
  String getemail="";
  String getdesignation="";
  String getaccesstoken="";   
  String getdate;
  String getTime;

// ignore: must_be_immutable
class EmployeeNavigation extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return EmployeeNavigationState();
  }
}
class EmployeeNavigationState extends State<EmployeeNavigation> {
  
  var email;
  var designation;
  var date;
  bool valuefirst = false;
  String backtext="";

  @override
  Widget build(BuildContext context) {
   //i used this too but it doesn't work.
    return WillPopScope(
      onWillPop: () async {
        if (_selectedTab == 0) {
          return true;
        }
        setState(() {
          _selectedTab = 0;
        });
        return false;
      },
      
    child:Scaffold(    
    drawer:Emp_DrawerCode(),
    body:  _pageOptions[_selectedTab], 
    bottomNavigationBar: BottomNavigationBar(
     backgroundColor: Colors.blue[50],
    type: BottomNavigationBarType.fixed,
    currentIndex: _selectedTab,
    onTap: (value) {
      print(value);
      setState(() {
        _selectedTab = value;
      });
    },
    items: [
      BottomNavigationBarItem(icon: Icon(Icons.home), label: "Home"),
      BottomNavigationBarItem(icon: Icon(Icons.location_on), label: "Location"),
      BottomNavigationBarItem(
        icon: Icon(Icons.person),
        label: "Profile",
      ),
    ],
  )));
  
}
}



class Emp_DrawerCode extends StatefulWidget {
  @override
  _Emp_DrawerCodeState createState() => _Emp_DrawerCodeState();
}

class _Emp_DrawerCodeState extends State<Emp_DrawerCode> {

  SharedPreferences myPrefs;
  name() async{
     myPrefs=await SharedPreferences.getInstance();
    setState(() {
          getname=myPrefs.getString('name');
          getemail=myPrefs.getString('email');
          getdesignation=myPrefs.getString('designation');
   
        });
    
  }
  void initState(){
    name();
  }

  @override
  Widget build(BuildContext context) {
    return new Drawer(
      child: new ListView(
          padding: const EdgeInsets.all(0.0),
          children: <Widget>[
            
            new UserAccountsDrawerHeader(
                accountName: new Text(getname),
                accountEmail: new Text(getemail),
                currentAccountPicture: new CircleAvatar(
                  backgroundColor:
                  Theme.of(context).platform == TargetPlatform.android
                      ? Colors.white
                      : Colors.blue,
              child: Text(
                getname[0][0],
                style: TextStyle(fontSize: 40.0),
              ),
            ),
          ),
          new ListTile(
              title: new Text('Home'),
              leading: Icon(Icons.dashboard,color:Colors.grey),
              onTap: (){
                Navigator.pop(context);
                  Navigator.push(context, new MaterialPageRoute(
                    builder: (context)=> EmployeeNavigation()
                    )
                  );
              },
            ),
            new ListTile(
              title: new Text('Request for leave'),
              leading: Icon(Icons.request_page,color:Colors.grey),
              onTap: (){
                Navigator.pop(context);
                  Navigator.push(context, new MaterialPageRoute(
                    builder: (context)=>RequestForLeave()
                    )
                  );
              },
            ),
            new ExpansionTile(
              title: new Text('History'),
              children: <Widget>[
                ListTile(
                   title:new Text("My Attendance"),
                  leading: Icon(Icons.assessment_outlined ,color:Colors.grey),
                  onTap: (){
                Navigator.pop(context);
                  Navigator.push(context, new MaterialPageRoute(
                    builder: (context)=>new MyAttendance()
                    )
                  );
              },
                 
                ),
                ListTile(
                   title:new Text("Leaves"),
                  leading: Icon(Icons.assessment_outlined,color:Colors.grey ),
                  onTap: (){
                Navigator.pop(context);
                  Navigator.push(context, new MaterialPageRoute(
                    builder: (context)=>new LeaveHistory()
                    )
                  );
              },
                 
                ),
              ],
              leading: Icon(Icons.history,),
            
            ),
           
            new ListTile(
              title: new Text('Log out'),
              leading: Icon(Icons.logout,color:Colors.grey),
              onTap: (){
                myPrefs.setBool('login', true);
                Navigator.pop(context);
                  Navigator.push(context, new MaterialPageRoute(
                    builder: (context)=>
                    
                    Login()
                    )
                  );
              },
            ),
            
            ],
            
        ),
        

      
    );
  }
}

kindly please help how to do this.

TimeToCode
  • 1,458
  • 3
  • 18
  • 60

3 Answers3

2

I am using navigator.push method and it is acting as you want.

appBar: AppBar(
  leading: IconButton(
    icon: Icon(Icons.arrow_back, color: Colors.blue),
    onPressed: () => Navigator.of(context).pop(),
  ), 
  title: Text("Sample"),
  centerTitle: true,
),

I wish it solve your problem.

Z_Z
  • 127
  • 7
  • but i used drawer icon on appbar, i can't use this, is there any other way? on more thing is android back button work same as this icon on appbar? – TimeToCode Aug 10 '21 at 12:02
  • You can add a `Row` widget and then add your drawer icon and that back button @TimeToCode – Viraj Doshi Aug 10 '21 at 12:23
  • but it will not a good idea to use 2 icon on appbar , i want to get it done with android back button, and mostly users use their phone back button. – TimeToCode Aug 10 '21 at 12:28
  • Before you send user to new page you clean page history. `Navigator.pop(context); Navigator.push(context, ...` Could you delete navigator.pop and then could you try this. It have to solve the problem. If everything is not clear just let me know. @TimeToCode – Z_Z Aug 11 '21 at 12:39
  • @Z_Z i did that, but when i press the back button, it goes to login screen (which is first screen of my app) and then when i click the login button it display the screen which i visited last. – TimeToCode Aug 11 '21 at 12:52
  • It showing that there is no problem because in those tabs u dont use nevigator.push. To do make this as you want you can use BottomAppBar with onPressed methods to call the pages `(Navigator.of(context).pushName('/yourScreenHere')` instead BottomNavigationBar. For log out option you must use a authentication method simplest way change a boolean function when you log in or log out. And check this boolean if it is true then app allow to pass next screen. – Z_Z Aug 11 '21 at 14:51
1

Firstly Wrap your Scaffold with WillPopScope

    return WillPopScope(
      onWillPop: _onBackPressed,
      child : Scaffold());

And then you can call the Function that handles the back press.

// Back Button Android Behaviour
      Future<bool> _onBackPressed() async {
        final shouldPop = await showDialog(
            context: context,
            builder: (context) => AlertDialog(
                  title: Text(
                    "Are you sure you want to leave this page?",
                    style: TextStyle(
                      color: Colors.black,
                      fontSize: 25.0,
                      fontWeight: FontWeight.w500,
                    ),
                  ),
                  actions: <Widget>[
                    SizedBox(width: 16),
                    InkWell(
                      onTap: () {
                        Navigator.pushAndRemoveUntil(
                          context,
                          MaterialPageRoute(
                            builder: (BuildContext context) => HomeScreen(), // Destination
                          ),
                          (route) => false,
                        );
                      },
                      child: Container(
                        padding: EdgeInsets.all(8.0),
                        child: Text(
                          "LEAVE",
                          style: TextStyle(
                            color: Colors.red,
                            fontSize: 20.0,
                            fontWeight: FontWeight.w500,
                          ),
                        ),
                      ),
                    ),
                    SizedBox(width: 8.0),
                    InkWell(
                      onTap: () => Navigator.of(context).pop(false),
                      child: Container(
                        padding: EdgeInsets.all(8.0),
                        child: Text(
                          "DO NOT LEAVE",
                          style: TextStyle(
                            color: Colors.black,
                            fontSize: 20.0,
                            fontWeight: FontWeight.w500,
                          ),
                        ),
                      ),
                    ),
                  ],
                ));
        return shouldPop ?? false;
      }
awh
  • 15
  • 7
0

You need to first clarify your question a bit more.

Are using page view/ are you talking about a scenario where all are separately navigable screens or some different scenario ?

I am considering it as the second scenario when all are separately navigable screens.

In that case, every time user navigates to next screen you must use Navigator.pushNamed() / Navigator.push() as for now I think you are using Navigator.pushReplacement() which is causing this issue probably.

Navigator is nothing but a class aware of the stack of screens in the memory and so are the functions it provides us with. A simple push would mean pushing over the last pushed screen whereas pushing a replacement would replace the last pushed screen ultimately preventing you from navigating to the last pushed screen. Exactly like how it would work for a stack data structure.

ldev
  • 103
  • 1
  • 6