A Simple BottomAppBar in Flutter
In a project that I am currently working on — I will be sharing that soon, I needed to include a BottomNavigationBar. But not just any bottom navigation bar, I wanted it to be just a little bit fancy and cool.
The BottomNavigationBar is a widget which allows us to display a row of other smaller widgets either icons and/or labels at the bottom of the app. It enables us to select one item at a time and quickly move to that given page/UI. It is recommended to have between 2–5 items in a bottom navigation bar. For anything more than that, the navigation drawer or tabs are better.
Implementation
To have a bottom navigation bar in Flutter, the build method needs to return the Scaffold widget.
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Bottom Navigation Bar'),
centerTitle: true,
),
body: const Center(),
);
}
}
The Scaffold widget has a bottomNavigationBar property which will allow us to add the BottomAppBar widget. I am using the BottomAppBar instead of the BottomNavigationBar as I wanted to add a ‘notch’ in my navigation bar — hence the “little bit fancy and cool” bit.
The BottomAppBar has the following properties which I wanted to make use of:
- shape — adds a notch in the navigation bar hence making room for an overlapping floating action button (FAB)
- notchMargin — the margin between the navigation bar notch and the FAB
- clipBehavior — dictates whether the content will be clipped (or not) based on the option set here
bottomNavigationBar: BottomAppBar(
shape: const CircularNotchedRectangle(),
notchMargin: 5.0,
clipBehavior: Clip.antiAlias,
child: SizedBox(
height: kBottomNavigationBarHeight,
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
IconButton(
icon: const Icon(Icons.home),
onPressed: () {
setState(() {
});
},
),
IconButton(
icon: const Icon(Icons.search),
onPressed: () {
setState(() {
});
},
),
IconButton(
icon: const Icon(Icons.favorite_border_outlined),
onPressed: () {
setState(() {
});
},
),
IconButton(
icon: const Icon(Icons.account_circle_outlined),
onPressed: () {
setState(() {
});
},
)
],
),
),
),
Now, to make use of the BottomAppBar properties, we’ll need to add our FAB with the property: centerDocked
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
floatingActionButton: FloatingActionButton(
onPressed: () {},
child: const Icon(Icons.add),
),
So with that, we’re now able to get that ‘different’ looking bottom navigation bar.
However, as simple as that implementation seems, I had quite a task in trying to make it work. For starters, I noticed that the BottomAppBar doesn’t have the currentIndex property which allows us to know what icon is selected in order to navigate the pages accordingly. It also doesn’t have the selectedItemColor and unselectedItemColor properties that allow us to switch the icon colours when their respective screens are navigated to.
So for that, we might need to make use of the BottomNavigationBar as a child of the BottomAppBar. Also, we’ll use a pageController to allow us to switch between these screens/pages.
bottomNavigationBar: BottomAppBar(
shape: const CircularNotchedRectangle(),
notchMargin: 5.0,
clipBehavior: Clip.antiAlias,
child: SizedBox(
height: kBottomNavigationBarHeight,
child: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
backgroundColor: Colors.green,
currentIndex: _selectedIndex,
selectedItemColor: Colors.white,
unselectedItemColor: Colors.black,
onTap: (index) {
setState(() {
_selectedIndex = index;
pageController.jumpToPage(index);
});
},
items: const [
BottomNavigationBarItem(
icon: Icon(Icons.home_outlined),
label: '',
),
BottomNavigationBarItem(
icon: Icon(Icons.search),
label: '',
),
BottomNavigationBarItem(
icon: Icon(Icons.favorite_border_outlined),
label: '',
),
BottomNavigationBarItem(
icon: Icon(Icons.account_circle_outlined),
label: '',
),
],
),
),
),
body: PageView(
controller: pageController,
children: const <Widget>[
Center(
child: Home(),
),
Center(
child: Search(),
),
Center(
child: Favourite(),
),
Center(
child: Profile(),
),
],
),...
Here is the full code:
Let me know how I can improve on this implementation (e.g., the spacing of the icons next to the notch could be better when there are four navigation items. It looks okay when it’s just two items.)
Thank you for reading ❤