I have this problem. My home page has a bottomNavigationBar with 2 pages A and B.
Pages A and B have buttons that when tapped navigate to other pages which don't have bottom Navigation Bars. Now, when I am in these other pages that don't have bottom navigation bars and would like to return to my home page, that is the pages with bottom Navigation bars (A & B), using "Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (context) => A()), (Route route) => false),", the bottom Navigation Bar in page A disappears. The same happens when I navigate to page B.
How can I "pushAndRemoveUntil" to either pages (A & B) in my home page without losing the bottom Navigation Bar?
This is how I have implemented the bottom Navigation Bar:
return Scaffold(
backgroundColor: Theme.of(context).backgroundColor,
body: PageView(
children: <Widget>[
A(),
B(),
],
controller: pageController,
onPageChanged: onPageChanged,
physics: NeverScrollableScrollPhysics(),
),
bottomNavigationBar: CupertinoTabBar(
backgroundColor: appbar_Color,
currentIndex: pageIndex,
onTap: onTap,
activeColor: Theme.of(context).primaryColor,
items: [
BottomNavigationBarItem(
title: Text("Page A"),
icon: Icon(Icons.whatshot),
),
BottomNavigationBarItem(
title: Text("Page B"),
icon: Icon(Icons.notifications_active),
),
],
),
);
my onTap function:
onTap(int pageIndex) {
pageController.animateToPage(pageIndex,
duration: Duration(milliseconds: 100), curve: Curves.easeInOut);
}
Thank you so much.
You just need to call Navigator.pop(context) on other pages as they are just a stack on top of your current Scaffold containing PageView of 2 Pages. Just pop the page out and you will be redirected with the same screen.
It doesn't seem that you want to use pushAndRemoveUntil that push the given route onto the navigator, and then remove all the previous routes until the predicate returns true. It seems that you want to use pop (one view back) or popUntil (back until finding requested one)
This command will take you directly to the first view in the stack
Navigator.of(context).popUntil((route) => route.isFirst);
This other command will go one view back in the stack
Navigator.of(context).pop();
Related
I'm new to flutter and I'm trying to implement a persistent bottom navigation bar with the "persistent_bottom_nav_bar 4.0.2" plugin.
The issue I'm running into is, that I have to declare my AppBar in the page that implements the bottom bar, since that is where my scaffold is and the screens are just widgets loaded by the plugin into this scaffold. Now, if I'm navigating to a different page from one of the tabs, I want the AppBar to show a back button. For that I need to add an AppBar in the page I'm navigating to, but then I have two AppBars stacked. Thus, I need to hide the AppBar from the bottom bar page when I push pages into the navigator stack of the active tab.
Currently I'm trying to get the name of the route with ModalRoute.of(context)?.settings.name and compare it with the name of the route of the page that holds the bottom bar, and if they're not equal I can pass an argument back and hide the app bar. (I'm open for better solutions, that's the first I came up with). The problem is, that the named route does not work on the navigators of the different tabs. I'm getting something like this as the name: /9f580fc5-c252-45d0-af25-9429992db112.
My HomePage looks like this:
#override
Widget build(BuildContext context) {
print(ModalRoute.of(context)?.settings.name); // this gives me the correct route name
return Scaffold(
appBar: _showAppBar ? MyAppBar("") : null,
body: PersistentTabView(
context,
controller: _controller,
screens: _buildScreens(),
items: _navBarsItems(),
confineInSafeArea: true,
popAllScreensOnTapOfSelectedTab: true,
popActionScreens: PopActionScreensType.all,
navBarStyle: NavBarStyle.style6,
));
}
List<PersistentBottomNavBarItem> _navBarsItems() {
return [
PersistentBottomNavBarItem(
routeAndNavigatorSettings: const RouteAndNavigatorSettings(onGenerateRoute:
router.generateRoute),
icon: const Icon(Icons.add_circle_outline),
title: ("Add"))
];
}
List<Widget> _buildScreens() {
return [
const AddPage(),
];
}
On the AddPage (which is one of the tab views and only a widget without scaffold) I want a button, that navigates to a different screen. If that happens I want to hide the AppBar from the home_page and show the AppBar of this page to have the back navigation.
I do the navigation like this:
child: IconButton(
icon: const Icon(Icons.add),
color: Colors.white,
onPressed: () {
Navigator.pushNamed(context, AddCollectionRoute, arguments: 'test');
RouteSettings? routeSettings = ModalRoute.of(context)?.settings;
},
),
But here I now have "/9f580fc5-c252-45d0-af25-9429992db112" as name and null as argument.
Routes are generated like this:
Route<dynamic> generateRoute(RouteSettings settings) {
switch (settings.name) {
case AddCollectionRoute:
return MaterialPageRoute(builder: (context) => const AddCollectionPage());
case HomeRoute:
return MaterialPageRoute(builder: (context) => const HomePage());
}
}
So my questions are:
Why are the routes in the tabs anonymous and why are the arguments gone? Up until the HomePage everything works as expected.
Is there a better approach to hide the AppBar on navigation?
I'm stuck with a situation in flutter. I have a two tabs, each tab has a navigator. Each navigator can show a set of pages.
When on the first tab I would like to click a link on page one and be taken to the second tab and shown page three. Effectively deep linking from a page under tab one to a page under tab three. When navigating to page three, tab two should become active.
I have the tabs hosted in the typical way using a tab controller:
child: DefaultTabController(
length: 2,
child: Scaffold(
appBar: TabBar(
tabs: const [
Tab(text: 'HOME'),
Tab(text: 'MENU'),
],
),
body: TabBarView(
children: <Widget>[
HomeScreen(),
MenuScreen(),
],
),
),
),
From inside a page with a tab, I can access the tab controller by doing:
onTap: () async {
TabController tab = DefaultTabController.of(context);
tab.animateTo(1);
},
But I'm unsure of how to access the TAB2's navigator to push the page to have it navigate to page 3.
Feel like I'm missing something simple. Appreciate any advice :)
I ended up using vRouter with nested routes: https://vrouter.dev/guide/Examples/Nesting
I have bottom navigation bar and drawer. I want the drawer to close automatically when ever the user click any button navigation icon. I'm not really sure how to do that.
I can close the drawer immediately when ever the user click inside the drawer like below
void _onSelectItem(int index) {
setState(() => _currentSelected= index);
Navigator.of(context).pop(); // close the drawer
}
But the drawer stuck there forever until I slide back. I also want the drawer to close immediately when ever the user click bottom navigation bar.
void onTappedBar(int index){
index == 3
? _drawerKey.currentState.openDrawer()
: setState((){
_currentSelected = index;
});
}
And this are my bottom navigation bar
bottomNavigationBar: BottomNavigationBar(
backgroundColor: Colors.blueGrey[900],
type: BottomNavigationBarType.fixed,
onTap: onTappedBar,
currentIndex: _currentSelected,
showUnselectedLabels: true,
unselectedItemColor: Colors.white,
selectedItemColor: Color.fromRGBO(10, 135, 255, 1),
items: <BottomNavigationBarItem> [
BottomNavigationBarItem(icon: new Icon(Icons.home), title: new Text('Home')),
BottomNavigationBarItem(icon: new Icon(Icons.search), title: new Text('Explore')),
BottomNavigationBarItem(icon: new Icon(Icons.device_hub), title: new Text('Channels')),
BottomNavigationBarItem(icon: new Icon(Icons.dehaze), title: new Text('More')),
],
),
I'm current learning Flutter so any suggestion will be very appreciated. thanks
Add onTap: (int index) {} to your Bottom Nav Bar scaffold, and within that method add Navigator.of(context).pop();. Hope this helps.
I have one application of tabbars. one tab have textfield. It shows keyboard. I want to hide keyboard after press ob any other tab. I used below code but its still not working on other tabs.
return new Scaffold(
key: _scaffoldKey,
resizeToAvoidBottomInset: false,
backgroundColor: blackColor,
body: GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
FocusScope.of(context).requestFocus(new FocusNode());
},
child: Stack(children: <Widget>[
_showForm(),
],)
),
);
you can use onTap under TabBar() like this:
TabBar(
onTap: (_) => FocusManager.instance.primaryFocus?.unfocus(),
tabs: [
tab1(),
tab2(),
)
this will make every tab unfocus the keyboard and move to other tab as well
Use FocusScope.of(context).unfocus() when tab change.
when you click to change tab write below line :
FocusScope.of(context).requestFocus(new FocusNode());
How do I create a fullscreenDialog that covers my bottomnavigationbar?
My mainscreen looks like this, where I have a bottomnavigationbar which navigates to three different screens.
#override
Widget build(BuildContext context) {
return new Scaffold(
body: PageView(
children: [new HomeTab(), new PresentationsTab(), new TestTab()],
controller: _pageController,
onPageChanged: pageChanged,
),
bottomNavigationBar: new BottomNavigationBar(
currentIndex: _page,
onTap: tapBottomNav,
items: [
new BottomNavigationBarItem(
icon: new Icon(Icons.home),
title: new Text('Home'),
),
new BottomNavigationBarItem(
icon: new Icon(Icons.pregnant_woman),
title: new Text('Presentation'),
),
new BottomNavigationBarItem(
icon: new Icon(Icons.pregnant_woman),
title: new Text('Presentation'),
)
],
),
);
}
And somewhere I have a screen which navigates to another screen with the fullscreenDialog flag set to true like this.
Navigator.push(
context,
new MaterialPageRoute(
builder: (BuildContext context) => new AddAudio(),
fullscreenDialog: true,
),
);
On my appbar I can see that the flag actually works because my backbutton arrow will become an x, but my bottomnavigationbar will still be visible, how do I resolve this?
I have an answer for you on my post: Flutter MaterialPageRoute as fullscreenDialog appears underneath BottomNavigationBar
But, to recap for you:
I assume you are presenting your modal from a page which is itself a Scaffold? In which case you have nested Scaffold objects, and this is where the problem lies. To ensure your modal appears above the BottomNavigationBar you need to include that widget in the child Scaffold and not in the root one.
This seems like an utter pain in the arse, and not a great solution with loads of boilerplate and code duplication; but it isn't. You just need to build a custom composition widget for BottomNavigationBar and then use ChangeNotifier with a state class to manage state. I've explained it in the post I reference above, and it is probably better to read the answer there so you understand the context.
That is probably the expected behavior, you should push a PageRoute (with a PageRouteBuilder) and use a custom transition to have the bottom to top slide animation.