I'm making a project with 4 different pages. I use a "BottomNavigationBar" widget to navigate to each page. When an icon in the "BottomNavigationBar" is pressed, I display a different page in the Scaffold body. I don't use any routing so when a user presses back on Android, the app closes. Something I don't want happening.
All the guides I have found reload the whole "Scaffold" when navigating, but I want to only update the "body" property of the "Scaffold" widget. When a Navigation.pop()
occurs I again only want the "Scaffold" body to change.
I have found a post around the same issue, but the answer didn't work for me.
Another workaround I can try is making a custom history list, that I then update when pages are changed. Catching OnWillPop event to update the pages when the back button is pressed. I haven't tried this because I feel like there has to be a better way.
The Scaffold widget that displays the page.
Widget createScaffold() {
return Scaffold(
backgroundColor: Colors.white,
appBar: EmptyAppBar(),
body: _displayedPage,
bottomNavigationBar: createBottomNavigationbar(),
);
}
The BottomNavigationBar widget.
Widget createBottomNavigationbar() {
return BottomNavigationBar(
type: BottomNavigationBarType.fixed,
currentIndex: _selectedIndex,
onTap: _onItemTapped,
items: [
BottomNavigationBarItem(
icon: new Icon(Icons.home,
color: _selectedIndex == 0 ? selectedColor : unselectedColor),
title: new Text('Home',
style: new TextStyle(
color:
_selectedIndex == 0 ? selectedColor : unselectedColor)),
),
BottomNavigationBarItem(
icon: new Icon(Icons.show_chart,
color: _selectedIndex == 1 ? selectedColor : unselectedColor),
title: new Text('Month',
style: new TextStyle(
color:
_selectedIndex == 1 ? selectedColor : unselectedColor)),
),
BottomNavigationBarItem(
icon: Icon(Icons.history,
color: _selectedIndex == 2 ? selectedColor : unselectedColor),
title: Text('History',
style: new TextStyle(
color: _selectedIndex == 2
? selectedColor
: unselectedColor))),
BottomNavigationBarItem(
icon: Icon(Icons.settings,
color: _selectedIndex == 3 ? selectedColor : unselectedColor),
title: Text('Settings',
style: new TextStyle(
color: _selectedIndex == 3
? selectedColor
: unselectedColor)))
],
);
}
Methods that update the state of the displayed page.
void _onItemTapped(int index) {
_changeDisplayedScreen(index);
setState(() {
_selectedIndex = index;
});
}
void _changeDisplayedScreen(int index) {
switch (index) {
case 0:
setState(() {
_displayedPage = new LatestReadingPage();
});
break;
case 1:
setState(() {
_displayedPage = new HomeScreen();
//Placeholder
});
break;
case 2:
setState(() {
_displayedPage = new HomeScreen();
//Placeholder
});
break;
case 3:
setState(() {
_displayedPage = new HomeScreen();
//Placeholder
});
break;
default:
setState(() {
_displayedPage = new LatestReadingPage();
});
break;
}
}
}
What I want is to be able to use the Flutter Navigation infrastructure, but only update the body property of the Scaffold widget when changing pages. Instead of the whole screen.
A lot like the Youtube app or Google news app.
A bottom navigation bar is a material widget that is present at the bottom of an app for selecting or navigating to different pages of the app. It is usually used in conjunction with a Scaffold, where it is provided as the Scaffold. bottomNavigationBar argument.
Showing BottomNavigationBar Scaffold( appBar: AppBar( title: const Text('BottomNavigationBar Demo'), ), bottomNavigationBar: BottomNavigationBar( items: const <BottomNavigationBarItem>[ BottomNavigationBarItem( icon: Icon(Icons. call), label: 'Calls', ), BottomNavigationBarItem( icon: Icon(Icons.
I have added an answer to the post that you linked: https://stackoverflow.com/a/59133502/6064621
The answer below is similar to the one above, but I've also added unknown routes here:
What you want can be achieved by using a custom Navigator.
The Flutter team did a video on this, and the article they followed is here: https://medium.com/flutter/getting-to-the-bottom-of-navigation-in-flutter-b3e440b9386
Basically, you will need to wrap the body of your Scaffold in a custom Navigator
:
class _MainScreenState extends State<MainScreen> {
final _navigatorKey = GlobalKey<NavigatorState>();
// ...
@override
Widget build(BuildContext context) {
return Scaffold(
body: Navigator(
key: _navigatorKey,
initialRoute: '/',
onGenerateRoute: (RouteSettings settings) {
WidgetBuilder builder;
// Manage your route names here
switch (settings.name) {
case '/':
builder = (BuildContext context) => HomePage();
break;
case '/page1':
builder = (BuildContext context) => Page1();
break;
case '/page2':
builder = (BuildContext context) => Page2();
break;
default:
throw Exception('Invalid route: ${settings.name}');
}
// You can also return a PageRouteBuilder and
// define custom transitions between pages
return MaterialPageRoute(
builder: builder,
settings: settings,
);
},
),
bottomNavigationBar: _yourBottomNavigationBar,
);
}
}
Within your bottom navigation bar, to navigate to a new screen in the new custom Navigator
, you just have to call this:
_navigatorKey.currentState.pushNamed('/yourRouteName');
If you don't used named routes, then here is what you should do for your custom Navigator
, and for navigating to new screens:
// Replace the above onGenerateRoute function with this one
onGenerateRoute: (RouteSettings settings) {
return MaterialPageRoute(
builder: (BuildContext context) => YourHomePage(),
settings: settings,
);
},
_navigatorKey.currentState.push(MaterialPageRoute(
builder: (BuildContext context) => YourNextPage(),
));
To let Navigator.pop
take you to the previous view, you will need to wrap the custom Navigator
with a WillPopScope
:
@override
Widget build(BuildContext context) {
return Scaffold(
body: WillPopScope(
onWillPop: () async {
if (_navigatorKey.currentState.canPop()) {
_navigatorKey.currentState.pop();
return false;
}
return true;
},
child: Navigator(
// ...
),
),
bottomNavigationBar: _yourBottomNavigationBar,
);
}
And that should be it! No need to manually handle pop too much or manage a custom history list.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With