how send value when press back button flutter? - android

I have a simple code
class A_View extends StatelessWidget {
#override
Widget build(BuildContext context) {
return ViewModelBuilder<A_ViewModel>.reactive(
viewModelBuilder: () => A_ViewModel(),
builder: (context, model, child) => Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back, color: Colors.white),
onPressed: () => Navigator.pop(context, model.value)),
),
body: model.isBusy
? CircularProgressIndicator()
: ListView.builder(
.............
),
),
);
}
}
class A_ViewModel extends FutureViewModel {
int value = 10;
}
when i click button back in appbar . i was get value form pop
but when i click back button on my phone -> value is null
how to back button on my phone return value same button in appbar ?, please help me

To get the value from the back button pressed on your phone, you can use the willPopScope widget. Have a look into the below code:
return ViewModelBuilder<A_ViewModel>.reactive(
viewModelBuilder: () => A_ViewModel(),
builder: (context, model, child) => WillPopScope(
//here you can do the magic
onWillPop: ()async{
Navigator.pop(context, model.value);
return Future<bool>.value(false);
},
child:Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back, color: Colors.white),
onPressed: () => Navigator.pop(context, model.value)),
),
body: model.isBusy
? CircularProgressIndicator()
: ListView.builder(
.............
),
)
)
);

Related

Flutter: How do i disable double pressed on IconButton

I have some IconButton in persistentFooterButtons that navigate to other screens but if I pressed double on any button and press the back button it redirects two times. if I pressed the button multiple times and press the back button it shows me the same page. so I want to click only one time and when it clicks and shows me the page the button will disable and won't press I think it works but I know how do I do that. please help me with that issue.
Here is my code:-
class Footer extends StatefulWidget {
Footer({Key? key}) : super(key: key);
#override
_Footer createState() => _Footer();
}
class _Footer extends State<Footer>{
bool _isButtonTapped1 = false;
bool _isButtonTapped2 = false;
bool _isButtonTapped3 = false;
bool _isButtonTapped4 = false;
#override
Widget build(BuildContext context){
return MaterialApp(
home: Scaffold(
appBar: AppBar()
persistentFooterButtons: [
Row(
children: [
IconButton(
onPressed: () {
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(builder: (context) => const CardApp()),
(Route<dynamic> route) => false);
},
icon: SvgPicture.asset(
'assets/images/f_home.svg',
),
),
Spacer(),
IconButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Matches()),
);
},
icon: SvgPicture.asset(
'assets/images/f_fav.svg',
),
),
Spacer(),
IconButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Message()),
);
},
icon: SvgPicture.asset(
'assets/images/f_chat.svg',
),
),
Spacer(),
IconButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Favorites()),
);
},
icon: SvgPicture.asset(
'assets/images/f_star.svg',
),
),
]
)
],
),
);
}
}
Here is my code of persistentFooterButtons which added four buttons and each button navigates its own screen.
please help me ho disable multiple onPressed on every button. if anyone knows please help me out
if you want to prevent multiple press from user, in InkWell widget, use this:
onDoubleTap: (){},

how to handle the back button of andriod in flutter

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.
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.
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.
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;
}

Flutter WillPopScope for nested Navigation

I have Flutter App with nested Navigator and I want to override "onBackPressed" using WillPopScope in my nested screen.
Let's say I have MainScreen, PrimaryScreen, and SecondaryScreen.
PrimaryScreen is nested Navigator, it have several screen like PrimaryOneScreen, PrimaryTwoScreen, and PrimaryThreeScreen.
SecondaryScreen is also a nested Navigator, just like PrimaryScreen, it have 3 screens.
Here the illustration of what i want to achieve
MainScreen -> PrimaryScreen(PrimaryOneScreen -> PrimaryTwoScreen -> PrimaryThreeScreen)
When my position on PrimaryTwoScreen, I want to get back to PrimaryOneScreen with overriding "onBackPressed" using WillPopScope Widget. But onWillPop never called when I press back button, and my screen go back directly to MainScreen.
Here are my codes
MainScreen.dart
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
),
home: MainApp(),
onGenerateRoute: (settings){
WidgetBuilder builder;
switch(settings.name){
case 'primary' :
builder = (BuildContext _) => PrimaryScreen();
break;
case 'secondary' :
builder = (BuildContext _) => SecondaryScreen();
break;
case 'main' :
builder = (BuildContext _) => MainApp();
break;
default :
throw Exception('Invalid route: ${settings.name}');
}
return MaterialPageRoute(
builder: builder,
settings: settings
);
},
);
}
}
class MainApp extends StatelessWidget{
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
FlatButton(
onPressed: (){
Navigator.pushNamed(context, 'primary');
},
child: Text('To Page Primary'),
),
FlatButton(
onPressed: (){
Navigator.pushNamed(context, 'secondary');
},
child: Text('To Page Secondary'),
)
],
),
);
}
}
PrimaryScreen.dart
class PrimaryScreen extends StatelessWidget{
#override
Widget build(BuildContext context) {
return Navigator(
initialRoute: 'primary/pageone',
onGenerateRoute: (RouteSettings settings){
WidgetBuilder builder;
switch(settings.name){
case 'primary/pageone' :
builder = (BuildContext _) => PrimaryOneScreen();
break;
case 'primary/pagetwo' :
builder = (BuildContext _) => PrimaryTwoScreen();
break;
case 'primary/pagethree' :
builder = (BuildContext _) => PrimaryThreeScreen();
break;
default :
throw Exception('Invalid route: ${settings.name}');
}
return MaterialPageRoute(
builder: builder,
settings: settings
);
},
);
}
}
PrimaryOneScreen.dart
class PrimaryOneScreen extends StatelessWidget{
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Primary Page'),
),
body: Center(
child: Column(
children: <Widget>[
FlatButton(
onPressed: (){
Navigator.pushNamed(context, 'primary/pagetwo');
},
child: Text('To Page Two'),
),
FlatButton(
onPressed: (){
Navigator.pushNamed(context, 'primary/pagethree');
},
child: Text('To Page Three'),
),
],
),
),
);
}
}
PrimaryTwoScreen.dart
class PrimaryTwoScreen extends StatelessWidget{
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: ()async{
print('willPopScope');
Navigator.of(context, rootNavigator: false).pop();
return true;
},
child: Scaffold(
appBar: AppBar(
title: Text('Secondary Page'),
),
body: Center(
child: Column(
children: <Widget>[
FlatButton(
onPressed: (){
Navigator.pushNamed(context, 'primary/pageone');
},
child: Text('To Page One'),
),
FlatButton(
onPressed: (){
Navigator.pushNamed(context, 'primary/pagethree');
},
child: Text('To Page Three'),
),
],
),
),
),
);
}
}
PrimaryThreeScreen.dart
class PrimaryThreeScreen extends StatelessWidget{
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Primary Page'),
),
body: Center(
child: Column(
children: <Widget>[
FlatButton(
onPressed: (){
Navigator.pushNamed(context, 'primary/pageone');
},
child: Text('To Page One'),
),
FlatButton(
onPressed: (){
Navigator.pushNamed(context, 'primary/pagetwo');
},
child: Text('To Page Two'),
)
],
),
),
);
}
}
EDIT
I added an image to illustrate what I want to achieve.
How to pop only on nested navigator?
Thanks!
When pressing the back button, I think it will use the main navigator of your app, because it doesn't know the nested navigator what you want to interact with.
To solve it, you have to assign a key for your navigator to be able to use it later. And adding a WillPopScope at widget which you use your nested navigator to handle user action.
Based on your example, I added some code. Noting, the maybePop() function will call the WillPopScope of your widget of the nested navigator. If you call pop(), it will pop directly, ignoring the WillPopScope of your widget.
class PrimaryScreen extends StatelessWidget{
final _navigatorKey = GlobalKey<NavigatorState>();
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
if (_navigatorKey.currentState != null) {
_navigatorKey.currentState!.maybePop();
return false;
}
return true;
},
child: Navigator(
key: _navigatorKey,
initialRoute: 'primary/pageone',
onGenerateRoute: (RouteSettings settings) {
WidgetBuilder builder;
switch(settings.name){
case 'primary/pageone' :
builder = (BuildContext _) => PrimaryOneScreen();
break;
case 'primary/pagetwo' :
builder = (BuildContext _) => PrimaryTwoScreen();
break;
case 'primary/pagethree' :
builder = (BuildContext _) => PrimaryThreeScreen();
break;
default :
throw Exception('Invalid route: ${settings.name}');
}
return MaterialPageRoute(
builder: builder,
settings: settings
);
},
),
);
}
}
Try with this link https://medium.com/flutter-community/flutter-push-pop-push-1bb718b13c31
Check Use-case : pushReplacementNamed tag description

Close Navigation Drawer on Back Button Pressed in Flutter

I have a material designed Navigation Drawer in my very first flutter app. This work's fine but I did't find any way to close the Navigation Drawer on Back Button Press if it's open when use WillPopScope to show AlertDialog. The application just show AlertDialog instead of close the Drawer when back press. I want Drawer should close if already open and show AlertDialog otherwise.
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: onBackPressed,
child: Scaffold(
appBar: AppBar(
title: Text("Home"),
),
drawer: Drawer(
),
body: Center(
child: Text("Home"),
),
),
);
}
onBackPressed shows dialog to close the app.
Future<bool> onBackPressed() {
return showDialog(
barrierDismissible: false,
context: context,
builder: (context) => AlertDialog(
title: Text("Do you want to exit?"),
actions: <Widget>[
FlatButton(
onPressed: () => Navigator.pop(context, false),
child: Text("No")),
FlatButton(
onPressed: () => Navigator.pop(context, true),
child: Text("Yes"))
],
));
}
Can anybody guide me how can I achieve this?
You can copy paste run full code below
Step 1: You need Scaffold key to controll Drawer so you need GlobalKey<ScaffoldState> _key = new GlobalKey<ScaffoldState>();
Step 2: In onWillPop You can check isDrawerOpen and do Navigator.pop
code snippet
GlobalKey<ScaffoldState> _key = new GlobalKey<ScaffoldState>();
MyHomePage({Key key, this.title}) : super(key: key);
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
if (_key.currentState.isDrawerOpen) {
Navigator.of(context).pop();
return false;
}
return true;
},
child: Scaffold(
working demo
full code
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
print("My App Page");
//return false;
},
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: "test",),
),
);
}
}
class MyHomePage extends StatelessWidget {
final String title;
GlobalKey<ScaffoldState> _key = new GlobalKey<ScaffoldState>();
MyHomePage({Key key, this.title}) : super(key: key);
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
if (_key.currentState.isDrawerOpen) {
Navigator.of(context).pop();
return false;
}
return true;
},
child: Scaffold(
key: _key,
appBar: AppBar(title: Text(title)),
body: Center(child: Text('My Page!')),
drawer: Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
DrawerHeader(
child: Text('Drawer Header'),
decoration: BoxDecoration(
color: Colors.blue,
),
),
ListTile(
title: Text('page 2'),
onTap: () {
Navigator.push(
context, new MaterialPageRoute(builder: (context) => Page2()));
},
),
ListTile(
title: Text('Item 2'),
onTap: () {
// Update the state of the app
// ...
// Then close the drawer
Navigator.pop(context);
},
),
],
),
),
),
);
}
}
class Page2 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
print("Page2");
_popNavigationWithResult(context, 'from_back');
return false;
},
child: Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () {
_popNavigationWithResult(context, 'from_button');
},
),
body: Container(
child: Center(
child: Text('Page 2',
style: TextStyle(fontSize: 30.0, fontWeight: FontWeight.bold)),
),
),
),
);
}
void _popNavigationWithResult(BuildContext context, dynamic result) {
Navigator.pop(context, result);
}
}
my Back button was not working on drawer, because of my home screen. Remove WillPopScope from drawer and put following code in the home screen instead.
WillPopScope(
onWillPop: () async {
return Navigator.of(context).canPop();
},
child: Scaffold(
Simply add Navigator.pop(context);
ListTile(
title: const Text('Item 1'),
onTap: () {
// Update the state of the app
// ...
// Then close the drawer
Navigator.pop(context);
},
),

catch Android back button event on Flutter

Is there any way I can catch the onBackPressed event from Android back button?
I've tried the WillPopScope but my onWillPop function only triggered when I tap on the Material back arrow button
I put it like this:
class MyView extends StatelessWidget{
Widget build(BuildContext context) {
return new WillPopScope(
onWillPop: () async {
debugPrint("Will pop");
return true;
},
child: ScopedModel<AppModel>(
model: new AppModel(),
child: new Scaffold(......
I need to catch it because somehow my screen behaved incorrectly when it came to back button pressed, it pops the screen and the screen below it, but somehow, using material back arrow button works normal.
Update:
The code works, my problem was not in the pop of this screen, but on the previous screen, I use 2 MaterialApp widgets, and somehow it gave a weird behavior.
In order to prevent navigating back WillPopScope is the correct way and should be used as follow:
class Page2 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new WillPopScope(
child: new Scaffold(
appBar: new AppBar(
title: new Text('Page 2'),
),
body: new Center(
child: new Text('PAGE 2'),
),
),
onWillPop: () async {
return false;
},
);
}
}
Future<T> pushPage<T>(BuildContext context, Widget page) {
return Navigator.of(context)
.push<T>(MaterialPageRoute(builder: (context) => page));
}
Can call the page like:
pushPage(context, Page2());
This is should be helpful.
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () {
_moveToScreen2(context, );
},
child: Scaffold(
key: _scaffoldKey,
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
_moveToScreen2(context);
}),
title: Text("Screen 1"),
),
),
);
}
/**
* This is probably too thin to be in its own method - consider using
* `Navigator.pushReplacementNamed(context, "screen2")` directly
*/
void _moveToScreen2(BuildContext context) =>
Navigator.pushReplacementNamed(context, "screen2");
Use WillPopScope method and return false
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
// Do something here
print("After clicking the Android Back Button");
return false;
},
child: Scaffold(
appBar: AppBar(
title: Text("Handling the back button"),
),
body: Center(
child: Text("Body"),
),
),
);
}
Just adding an important point here.
Please note that by using WillPopScope, we will lose the back swipe gesture on iOS.
Reference: https://github.com/flutter/flutter/issues/14203
This code work for me.
I think there may be two reasons.
Child of WillPopScope is Scaffold
No return in onWillPop
return new WillPopScope(
onWillPop: () {
if (!_isOpened) Navigator.pop(context);
},
child: new Scaffold(
key: SharedService.orderScaffoldKey,
appBar: appBar,
body: new Builder(
builder: (BuildContext context) {
return page;
},
),
),
);
Another way todo this is to implement a NavigatorObserver and link it to the MaterialApp:
https://api.flutter.dev/flutter/widgets/RouteObserver-class.html
You don't have to use RouteAware, you can also implement your own NavigatorObserver.
This is for example how Flutter analytics works to automatically track screen opens/closes:
MaterialApp(
...
navigatorObservers: [
FirebaseAnalyticsObserver(analytics: analytics),
],
)
FirebaseAnalyticsObserver extends the RouteObserver which itself implements NavigatorObserver.
However WillPopScope is often the easier solution
You can use back_button_interceptor
it detects hardware back button & will be so useful specially in case of using persistent_bottom_nav_bar
#override
void initState() {
super.initState();
BackButtonInterceptor.add(myInterceptor);
}
#override
void dispose() {
BackButtonInterceptor.remove(myInterceptor);
super.dispose();
}
bool myInterceptor(bool stopDefaultButtonEvent, RouteInfo info) {
print("BACK BUTTON!"); // Do some stuff.
return false;// return true if u want to stop back
}
Following the documentation of BackButtonListener:
/// It can be useful for scenarios, in which you create a different state in your
/// screen but don't want to use a new page for that.
https://github.com/flutter/flutter/pull/79642
e.g.
#override
Widget build(BuildContext context) {
return BackButtonListener(
onBackButtonPressed: () {
/// todo: close search widget
if(searchBarController.isClose()){
return false;
}else{
searchBarController.close();
return Future.value(true);
}
},
child: SearchBar(controller: searchBarController),
);
}
This is the updated code
basically, WillPopScope -> onWillPop works on the future argument
we can say as when it happens then ????
so as soon the back button is pressed WillPopScope -> onWillPop gets activated and listens to the argument more specific the back button event to pop it (replace it)
Most of the time I use it to show a DialogBox of Future type because it will only appear when it is needed same can be used to navigate to a new screen as well (hope so) preferred to do MaterialPage routing or named routing techniques for navigation,
use WillPopScope for the hardware back button event listening (hardware = Android/IOs) to show the exit popup
code is already been given above but does not work for me so I change a little bit
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async{
return _moveToScreen2(context);
},
child: Scaffold(
key: _scaffoldKey,
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
_moveToScreen2(context);
}),
title: Text("Screen 1"),
),
),
);
}
Future<bool>_moveToScreen2(BuildContext context) =>
Navigator.pushReplacementNamed(context, "screen2");
===============================================
What I do on Exit
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: ()=> showExitPopup(context)
child: Scaffold(
key: _scaffoldKey,
appBar: AppBar(
title: Text("Screen 1"),
),
),
);
}
=========================================
On Back button Press
created a dart file with the name showExitPopup
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:vexpositions/Servises/ConstantManager.dart';
Future<bool> showExitPopup(context) async{
return await showDialog<bool>(
context: context,
builder: (BuildContext context) {
return AlertDialog(
content: SizedBox(
height: 90,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text("Want to Exit the app!"),
const SizedBox(height:20),
Row(
children: [
Expanded(
child: ElevatedButton(
onPressed: () {
print('yes selected');
exit(0);
},
style: ElevatedButton.styleFrom(
primary: Colors.white),
child: const Text("Yes", style: TextStyle(color:
Colors.black)),
),
),
const SizedBox(width: 15),
Expanded(
child: ElevatedButton(
onPressed: () {
print('no selected');
Navigator.of(context).pop();
},
style: ElevatedButton.styleFrom(
primary: Colors.red.shade800,
),
child: const Text("No", style: TextStyle(color:
Colors.white)),
))
],
)
],
),
),
);
});
}

Categories

Resources