from cart page i Navigate login page without persist nav page, its okey.
PersistentNavBarNavigator.pushNewScreen(
context,
screen: Login(),
withNavBar: false, // OPTIONAL VALUE. True by default.
pageTransitionAnimation: PageTransitionAnimation.cupertino,
);
but when login success i want navigate next page from cart page with persist nav bar
PersistentNavBarNavigator.pushNewScreen(
context,
screen: Nexpage(),
withNavBar: true, // OPTIONAL VALUE. True by default.
pageTransitionAnimation: PageTransitionAnimation.cupertino,
);
but its doesnot work
Related
I'm using persistent_bottom_nav_bar package and when I navigate to anew screen from an alertdialog the navigation bar disappears even when I use
'''
PersistentNavBarNavigator.pushNewScreen(
context,
screen: doseForm(
medName: medName,
)
withNavBar: true, // OPTIONAL VALUE. True by default.
pageTransitionAnimation: PageTransitionAnimation.cupertino,
);
'''
Using the mockingjay Flutter package, how do I verify in a widget test that an alert dialog has been displayed after e.g. tapping a button? The alert dialog is displayed using the showDialog function.
This is very similar to verifying page navigation behaviour, the thing that caught me out was the showDialog function must have the parameter useRootNavigator set to false, as documented in the example project. Without it the test will fail to detect that the alert dialog was displayed.
showDialog(
context: context,
useRootNavigator: false, // By default this is true, which won't work with Mockingjay
routeSettings: RouteSettings(name: 'verify_checkout_failure'),
builder: (context) {
return AlertDialog(title: Text('Checkout failed'));
});
Then in your test:
await tester.tap(find.byType(PlaceOrderButton));
verify(
() => mockNavigator.push(
any(
that: isRoute<void>(
whereName: equals('verify_checkout_failure'),
),
),
),
);
In my app, I have a homepage that has 5 tabs on the bottom. On each tabbed page, there is an app bar that has a '+' symbol as an action, which navigates you to a different page. The navigation with that '+' button to the new page is done with the following code, alongside the Flutter Platform Widgets package:
Navigator.of(context, rootNavigator: true)
.push(
platformPageRoute(
context: context,
builder: (context) => Page1(),
),
);
I use the platformPageRoute feature as an easy way to navigate with a native feel. Now, that works fine to navigate to a new page, but the issue comes when I use
Navigator.pop(context);
to navigate back to the original page. When I use that to navigate back to that original page, it pays no attention to the tab that was selected originally. For example, if I were originally on the second tab on the homepage and then use the '+' button on that tab and then finally use
Navigator.pop(context);
on that new page, it returns the first tab of the homepage. Is there any way of ensuring when I use the above command, it goes to the right tab? I have tried something along the lines of:
Navigator.popUntil(context, '/homepageTab2');
alongside a named route, to return to the correct tab on the homepage, although that returns a black screen. Why might that be? I have also tried using:
Navigator.pushAndRemoveUntil(
context,
platformPageRoute(
context: context,
builder: (context) =>
HomePage(selectedPage: 1),
),
(route) => false,
);
This does not work either, since it returns the selected/correct page tab content, but with the first tab selected. In addition, the other
'problem' for me is that the animation is a 'push' one and that doesn't 'match' with the animation when I have more often used
Navigator.pop(context);
to navigate back to a screen. Is there a way to maybe use pushAndRemoveUntil but then change the animation to match a pop animation?
Thanks!
EDIT:
I have just noticed that with the situation I have described above, it is actually returning the correct screen content when I use Navigator.pop(context); but the tab in the tab bar at the bottom is showing as the first tab, in the second tab's position, essentially duplicating the first tab, until I navigate to a new tab and back, at which time it shows the correct tab in the correct position. I hope that makes sense!
As it turns out, the issue wasn't related to Navigator.pop(context); being used. It was the way I was controlling the selected tab. I'm posting this as an answer incase it helps someone else.
Initially, I created late values for a tab controller and the current selected page, like so:
late TabController _tabController;
late ScrollController _scrollController;
late int _selectedPage;
Then, I created a list of widgets that represented the actual page to display for each selected tab:
List<Widget> _pageWidgets = <Widget>[
Page1();
Page2();
Page3();
Page4();
Page5();
];
Then (and I think this was the bit that wasn't working) I used initState() as follows:
void initState() {
super.initState();
// Initialising a value that allows the 'final' page selector to be changed
_selectedPage = widget.selectedPage;
// Initialising the tab controller
_tabController = TabController(
length: 5,
vsync: this,
initialIndex: _selectedPage,
);
// updating the tab index when a new item is selected
_tabController.addListener(() {
setState(() {
_selectedPage = _tabController.index;
//_tabIndex = _tabController.index;
});
});
// Creating the scroll controller
_scrollViewController = ScrollController();
// Scrolling view to top when a new tab is selected
_tabController.addListener(() {
setState(() {
_scrollViewController
.jumpTo(_scrollViewController.position.minScrollExtent);
});
});
}
I then controlled the page content like this:
body: _pageWidgets.elementAt(_selectedPage),
I'm not 100% sure why this wasn't working, although I believe it would have something to do with the fact that initState() would only be called during the build and therefore placing the functionality inside there would mean changes wouldn't be detected. Either way, my new method, which works perfectly, is:
/// Controls the screen to display first
int _index = 0;
/// Creating a navigation key to control tab bar navigation
final _navigationKey = GlobalKey<CurvedNavigationBarState>();
Then, within the Scaffold() I show the page content like this:
body: _pageWidgets.elementAt(_index),
And finally, within the navigation bar (which is the CurvedNavigationBar() package from pub.dev) I give it a key and the index:
key: _navigationKey,
index: _index,
And this controls it perfectly, showing the correct tab.
Sub-pages of a TabBarView cannot be navigated using Navigator.
You can use TabController to go to your desired tab page after awaiting Navigator.push():
await Navigator.of(context, rootNavigator: true)
.push(
platformPageRoute(
context: context,
builder: (context) => Page1(),
),
);
tabController.animateTo(<index of tab>);
This structure of my app navigation:
CupertinoTabScaffold ->tabBuilder:TabPage-> tabBar: CupertinoTabBar
My TabPage:
return MaterialApp(
navigatorKey: navKey,
home: child,
);
I have separate navigation in each tab. by clicking on the bottom tab, I go back to the beginning. this is my code and this is working now:
key.currentState!.pushNamedAndRemoveUntil('/', ModalRoute.withName('/'));
for each tab I have my own navigation key. I pass it to each TabPage.
but if the page is at the root I need to avoid pushing same route twice. I tried this code but it doesn't work:
key.currentState!.pushNamedAndRemoveUntil("/",
(route) => route.isFirst && route.settings.name == "/" ? false : true);
how avoid pushing same route twice?
Navigator.of(context).pushNamedAndRemoveUntil(
"newRouteName",
(route) => route.isCurrent && route.settings.name == "newRouteName"
? false
: true);
t will pop the current route if name of the route is "newRouteName" and then push new one, else will not pop anything.
Edit: Latest flutter provides ModalRoute.of(context).settings.name to get the name of current route.
If you're using a BottomNavigationBar, you can simply add a checker on onTap() to see if you're going to navigate on the same page. To track the current page, you can either use enum or a simple variables like int. CupertinoTabBar also have an onTap property available similar to BottomNavigationBar.
BottomNavigationBar(
items: <BottomNavigationBarItem>[...],
currentIndex: _currentPage,
onTap: (value){
// Only navigate if a different page was clicked
if(value != _currentPage){
_currentPage = value;
setState(() {
switch(value) {
// Page 0
case 0:
key.currentState!.pushReplacementNamed(...);
break;
// Page 1
case 1:
key.currentState!.pushReplacementNamed(...);
break;
...
}
});
}
}
)
Or if you're using a TabBar with TabBarView, the page displayed can be managed by the controller as demonstrated in this guide.
This will pop the current route if name of the route is the new Route Name and then push new one, else will not pop any route.
Navigator.of(context).pushNamedAndRemoveUntil(
"new",
(route) => route.isCurrent && ModalRoute.of(context).settings.name == "new"
? false
: true);
I want to call a function after modal bottom sheet built. But i could not check bottom sheet build. How can i check modal bottom sheet visibility and it is build?
showModalBottomSheet(context: context, builder: (context) => Container())
.then((value) => print('i am visible now!'));