Flutter: Custom BottomAppBar

Joshua Friso
8 min readMar 2, 2020

--

I’m writing this article with the purpose to help you, yes you, Flutter developer who finds beautiful designs on the internet and doesn’t understand how to create something like that, today I will pass to you how I created a BottomAppBar with animated FloatingActionButton (FAB).

You can say that there is a BottomNavigationBar for this, however, to create the above effect we need to use the BottomAppBar because BottomNavigationBar does not work very well in practice to give this space around the FloatingActionButton.

Centralizing the FAB

First, we create the Flutter project, then we create the archive home_page.dart and to assign it at home: of the main.dart.

Done this, we go to the archive home_page.dart and insert the FAB and the BottomAppBar on our Scaffold.

We use the Scaffold.floatingActionButtonLocation setting up as FloatingActionButtonLocation.centerDocked because doing this we can fit it in the center of our BottomAppBar.

We set up the shape too with CircularNotchedRectangle() on our BottomAppBar to generate this space around of the FAB.

However, the final result didn’t expect.

Huh, where is the BottomAppBar???

What we need to do is set a height for her, in this case, we put like a child a Container and set up a height: 60.0.

We can add color too like Colors.blueGrey to make possible we can see better the changes, we will change this later.

Better now, we have our BottomAppBar with our FAB centralized

Adding the tabs icons

Together with our FAB, we need to add the icons for the tabs to can see different pages.

For this, we need to make our code more organized and we will create the CustomBottomAppBar to separate our BottomAppBar as a generic Widget.

For this, we need to follow some criteria:

  • Show both 2 and 4 tabs (symmetrical design).
  • Highlight and follow the selected guide.
  • Trigger a callback function every time a tab is selected, causing the parent to switch the page.

First, we create a class called CustomAppBarItem where we put the following values than can be passed:

  • IconData: to receive the icon for the tab.
  • bool: this boolean serve to put a red badged above the icon indicating a notification.

After that, inside our widget, we have the following values than was expected at the moment:

  • onTabSelected: this is the callback function received from father.
  • items: a list of type CustomAppBarItem referent the information of the tabs to be shown

Note that within the constructors, we leave the expected attributes between {} as they are optional.

Inside our class State already, we create an integer _selectedIndex with the initial value 0, besides a function without return (void) _updateIndex where we called the callback function informing the value of the index and give a setState on _selectedIndex refreshing the value with the index.

Note that both the function and the variable of the integer type have a “_” before them, this indicates that they are private and can be used within this class.

Now, we go to create the method to generate our tabs according to the passed items on the list than we called items.

We started the widgets tree with the Expanded to ensure than each item has the same width inside of Row.

Following with a SizedBox to cover all height of BottomAppBar.

We use the InkWell inside the Material because he makes available a gesture detector onTap and provides us a splash effect of material when the widget is touched.

As a child of InkWell, we have an icon where we pass the icon to be displayed and in color, we use ternary to validate that the value of _selectedIndex is equal to the index, if positive it paints the icon blue, otherwise, leave it gray.

Inside the build, we use the List.generate to create the items tabs.

In the Row, we pass as a child the list items generated above besides altering the mainAxisAlignment.spaceAround ensuring the items stay equally spaced.

To test our CustomBottomAppBar we need to alter our HomePage, let’s see how it looks:

After the Hot Reload we have the following result:

We have a functional BottomAppBar in principle.

Enhancements

Yeah, yeah, we have a functional BottomAppBar, but we don’t want just it, do we?

Let’s give things a boost.

If we realized, the icons near the FAB are very close, with this we can create a separator.

Now we go to validate if was pass 2 or 4 items to the CustomBottomAppBar directly on the constructor.

But, how we insert the separator in the middle of list items? With an items.insert.

This way we can guarantee that we can receive both 2 and 4 items and that they were more separated in the middle, making the layout more beautiful.

Very nice and such, but how can I be sure that it is changing the page when I touch a tab? Let’s make a simple change to show this.

In our HomePage, we go to alter the integer _selectedIndex for a String _lastSelected than receive the initial value “TAB: 0”.

With that, we need to change our _selectedTab function where it will change the value of _lastSelected to receive the index value instead of 0.

In our Scaffold, we will place the body, which will be a Center with a Text child that receives _lastSelected with a font size of 32.

And the result is as follows:

One more thing that we can improve is the notification alert, remember it?

If bool is passed with a true value for the item it must have a red ball above the icon in the tab, for that we need to make some changes:

First, in the CustomAppBarItem constructor, we put this.hasNotification = false, so the default value will be false.

Then we validate through a ternary if the value of hasNotification is true, if it is, we will create a Stack wherein the children we will pass the Icon as it was before and another Icon that will be the red circle, inside a Positioned where we will set the top and the right.

To test, we have to go to the HomePage and include in one of the items that we have hasNotification: true.

That done, we will have the following result:

Now let’s take some action to our FAB.

First, we will put the animation to rotate it and change the icon.

For that, we will create the file FloatingButtonAnimated, in it, we will create the animation in a more organized way.

As soon as we create our file, we import the material and create a StatefulWidget, in the State’s class we declare that it will inherit the SingleTickerProviderStateMixin class

We then declare two variables, a boolean called isOpened and an AnimationController.

We created our initState where we will start the AnimationController, we will pass vsync with this value as it will indicate that what will be controlled is that widget beyond the duration. addListener will issue a setState to change the state.

Never forget to dispose of the controller, otherwise, it will be active even after the app is closed.

Then we create the animate function where if isOpened is false it will execute the animation in a normal way, otherwise, it will do it in reverse.

Anyway, in our build, we put our FloatingActionButton where we will pass the animate function to onPressed, as a child he will receive an AnimatedBuilder with the animation being the controller.

The return will be a Transform that allows us to pass a transformation on one of the axes (x, y, z), your child will receive an icon that will start with the “+” and after the animation, it will be the “X”.

To test it, let’s change our HomePage again so that it calls our animated widget.

And finally, we have this result:

Conclusion

We can still improve our BottomAppBar even more, but that’s for the next article. I hope you liked it and leave here in the comments what I would most like to see for this BottomAppBar.

Below is the Github link to see the complete code.

This BottomAppBar was based on the article:

--

--