I have bottom tab navigator that contains of A and B screens, inside B screen I have widget that navigate to C page and inside C page I want to add back arrow to go back to previous screen (B screen), so...
I have simple widget that the code looks like this
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
resizeToAvoidBottomPadding: false,
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () => Navigator.of(context).pop(),
),
title: Text("XXX"),
centerTitle: true,
),
body: detail()));
}
the problem is whenever I click back arrow.. it turns to black screen... I don't get any idea what the problem is... so is there a way to go to my previous screen?
and this is how I ndo navigate from B screen to C page
InkWell(
onTap: () {Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (context) => new NextScreen(check: values)));
},
child: Text(
"Next...",
style: TextStyle(
fontSize: 13.0,
),
),
)
The reason why you see a blank screen is because you navigated using pushReplacement. What pushReplacement does it that it will navigate to the next screen without stacking itself to the route meaning that it will make the app forget that the last screen was your screen B. Try using Navigator.push() instead.
Here is an example:
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => ScreenC()),
);
}
Related
I am working on the iPad and I have set up the screen to be SplitScreens. Thus I have two Navigators side by side. However, when I push a new Screen from the second Navigator I get a weird animation where the second screen (right) overlaps the first screen (left).
Please look at this video that explains it very good:
https://imgur.com/a/93UmrGm
SplitView(
menu: Navigator(
key: firstSplitNavigatorKey,
onGenerateRoute: (routeSettings) {
return MaterialPageRoute(
builder: (context) =>
const KursplanungScreen(title: 'Demo App'),
);
},
),
content: Navigator(
key: secondSplitNavigatorKey,
onGenerateRoute: (routeSettings) {
return MaterialPageRoute(
builder: (context) => const Scaffold(
body: Center(
child: Text(
"Herzlich Willkommen!"))),
);
},
),
menuWidth: 300,
),
Then somewhere in the second screen i call this:
TextButton(
onPressed: () => secondSplitNavigatorKey.currentState!.push(
MaterialPageRoute(
builder: (_) => const CourseOverviewScreen(),
),
),
child: const Text("Bearbeiten"),
),
How can I avoid that third weird animation?
You need to use a Navigator object to handle the right side pages.Use a Navigator object as widget father of the right side and handle the stack of pages to navigate only in this side. The default Navigator will change the entire page and will create a whole new one.
The left side, don't need to have a Navigator, only handle it using Widgets states(StatefullWidget or something like that).
SplitView(
menu: MenuSideBar(
onChangeSection: (Widget section) {
setState((){
pages.last=section;
});
}),
content: Navigator(
pages: pages,
),
),
Hi guys i want to chage the beheviour of exiting back button funcionality of Android's defaul bottom bar. In my app if i press the "arrow" it close the application but i want to it come back to previous screen. I don't know how to do it i tried with appBar but using onPressed () appears a black screen. Altrought my mind the best and elegant solution is to change the "arrow" beheviour and it also has to work for IOS. How can i do it?
This is the appBar code
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back, color: Colors.black),
onPressed: () => Navigator.of(context).pop(),
color: red,
),
),
if you want to change the behaviour of the bottom back button of app you can use onWillPop
WillPopScope(
onWillPop: () => backPress(),
child: Scaffold(
......
and backpress function decides what to do instead
Future<bool> backPress() async {
print("hellp");
return false;
}
My users will navigate to screen 1, then screen 2 then screen 3.
When they click the back button on screen 3, depending upon a variable in that screen, I want the back button to either take them back to screen 2 or screen 1.
Note: the back button must be trigger by the user, I don't to pragmatically navigate back.
I thought I could use WillPopScope but that can only return a bool.
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () {
return true
},
child: Scaffold(
...
),
);
}
,
Here's an example:
return WillPopScope(
onWillPop: () async => true,
child: Scaffold(
appBar: AppBar(
automaticallyImplyLeading: true,
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
_user.isRegistered
? Navigator.popUntil(context, (route) => route.isFirst) // Takes the user to the first page
: Navigator.push(context, MaterialPageRoute(builder: (context) => SecondRoute()));
},
),
I want to be able to transfer data from one screen to another. What I have now does work, but I want to be able to have icon in
the AppBar that will only go to the second page, and not take any arguments. For now I have this:
FIRST PAGE
This is the icon on the first page that adds the list tile arguments to the Cart screen (and only adds , it doesn't push the Cart screen, that
should be done below in the appbar.
child: IconButton(
icon: Icon(Icons.add),
onPressed: () => MaterialPageRoute(
builder: (context) =>
Cart(person.name, person.surname),
)),
Below in the scaffold I have this in the AppBar, the icon that should only push the Cart screen, and not any other values.
IconButton(
icon: Icon(Icons.add_shopping_cart, color: Colors.white),
//this will be the cart window ontap, change icon to something better
onPressed: () => Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) =>
Cart(//there should be arguments here, but I just want to go to Cart screen, the arguments were added in the first icon))),
This Cart class requires arguments (from the second page, like personName, personSurname), but I just want to be able to push
the second screen, and not have any arguments on there. It is the small cart icon in the appbar.
SECOND PAGE
Here is the second page (sudo cart screen) that should just take in the arguments from the first one.
class Cart extends StatefulWidget {
final String personName;
final String personSurname;
Cart(this.personName, this.personSurname);
#override
_CartState createState() => _CartState();
}
class _CartState extends State<Cart> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Cart'),
centerTitle: true,
),
body: Center(
child: Container(
child: Text('${widget.personName}, ${widget.personSurname}'))),
);
}
}
My issue is that I want to have the 2 separate functions for the cart. First one is on the first page where first icon
only adds the whatever argument I want to the cart, and the second icon in the app bar of first page just pushes the Cart screen.
In the second screen, I just want to have whatever data pushed from the first page.
Try it like this:
Declare two variables above:
String name = '';
String surname = '';
Assign your data to them:
child: IconButton(
icon: Icon(Icons.add),
onPressed: () {
name = person.name;
surname = person.surname;
},
And use them as arguments:
IconButton(
icon: Icon(Icons.add_shopping_cart, color: Colors.white),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) => Cart(name, surname))
),
I am using interceptor https://pub.dartlang.org/packages/back_button_interceptor to execute a method when the page 1 is back from page 2.
If I come back from page 2 to page 1 using device back button, the method is executed.
But if I come back from page 2 to page 1 using the arrow button at appBar I am not able to execute the method.
How can the back arrow button functionality default to the device back button?
You can surround your scaffold on Page 2 with WillPopScope, set onWillPop to false to prevent the page from being popped by the system and then add your own back button into the app bar's leading widget and perform your pop in there.
#override
Widget build(BuildContext context) {
return new WillPopScope(
onWillPop: () async => false,
child: new Scaffold(
appBar: new AppBar(
title: new Text("data"),
leading: new IconButton(
icon: new Icon(Icons.ac_unit),
onPressed: () => Navigator.of(context).pop(),
),
),
),
);
}
code for the answer from this post
Edit: Addition to Page 2 to control navigation
In addition to the above code you'll add the below code to page 2. Change
Navigator.of(context).pop()
to
Navigator.of(context).pop('upload_files')
Then in your page 1 where you navigate you'll await the navigation and use the result returned from the pop on page 2 and run your logic
var navigationResult = await Navigator.push(
context,
new MaterialPageRoute(
builder: (context) => Page2()));
if(navigationResult == 'upload_files') {
uploadFiles(); // Perform your custom functionality here.
}
The default back button in AppBar is BackButton widget from material.dart. You may create it manually and pass your own onPressed to do what you want:
return Scaffold(
appBar: AppBar(
leading: BackButton(onPressed: _onBackPressed),
title: Text('Title'),
),
body: Container(),
);
If you do not specify leading in AppBar, then it creates a BackButton with the handler that does Navigator.maybePop(context).