Flutter Tutorials – #1.8 – TabBar

Introduction

Welcome to Himdeve development, where we are preparing the best tutorials to make your mobile app development easier and more efficient.

Goal

  1. In the Portfolio screen we will create 2 tabs to switch between the two subpages of the portfolio – Portfolio Tutorials and Portfolio Gallery
  2. We will use components such as TabBar and TabBarView in combination with Slivers
  3. Finally, we’ll learn how to use TabBar instead of combining BottomNavigationBar with a PageView component.

Procedure

First we open our existing application from the previous tutorial and we open the portfolio_page.dart file. This will be our starting file for this tutorial.

Mixin

First, let’s explain the term Mixin.

Mixins allow us to add a group of “functions” to a class without using the parent-child hierarchy, allowing us to have one parent and multiple Mixin components in the same class. In our case we have the _PortfolioPageState class that inherits from the State class. And now if we wanted to inherit further features from another class without that class being the ancestor of our class, we could use Mixin. In simple words, we just use the functions of another special class without directly inheriting from it.

When we inherit from another class we use the extends command. For Mixins, we use the with command.

In this case, we use SingleTickerProviderStateMixin for the _PortfolioPageState class.

TabController

To be able to manipulate with the TabBar and TabBarView widgets, we need a TabController.

The TabController constructor has 2 required arguments. The first is length, which represents the number of tabs. And the second is vsync, which represents a TickerProvider. That’s why we use SingleTickerProviderStateMixin. We insert our class (this) into vsync argument, because it provides TickerProvider with SingleTickerProviderStateMixin.

TickerProvider

As the name suggests, TickerProvider provides a Ticker, which simply means that it returns a callback to our application about frame updates, means a screen redraw information, so that an AnimationController can generate a new value and redraw the animated widget. The AnimationController is created when we create a TabController and serves for animation between our tabs.

We initialize TabController in the initState method of the _PortfolioPageState class.

Copy to Clipboard

In the dispose method of the _PortfolioPageState class, we call the dispose method of the TabController to release the AnimationController that was created in it.

Copy to Clipboard

Next, we define the _pages list from the previous tutorial, which contains the tab name and subpage that appears when we click on the tab. This time, however, we will add information about the Icon type and therefore we will use the Tuple3 class.

Copy to Clipboard

In the build method of our Stateful Widget, we will return the Scaffold widget, where we insert the NestedScrollView widget into the body attribute so that we can use TabBar in combination with the Slivers.

Copy to Clipboard

To the body attribute of the NestedScrollView widget, we define a TabBarView, which has the controller attribute, where we insert our _tabController and the children attribute, in which we insert a list of our subpages. We will use the map function from the previous tutorial.

Copy to Clipboard

NestedScrollView has in addition to the body attribute, another required attribute, and that is headerSliverBuilder. It is a callback function that returns list of widgets.

First, we return the SliverAppBar widget using our PortfolioSliverAppBar class, which uses a title as an argument. We will enter the name of the currently displayed subpage here. We use the TabController index, which returns the current index of the page being displayed. And we take the title from our _pages list.

Copy to Clipboard

However, in order to rebuild the build method, we need to call the setState method when a subpage is changed.

So we add a listener to our TabController in the initState method of the _PortfolioPageState class, which will listen for a change to the subpage and call the setState method for that change.

Copy to Clipboard

We go back to the headerSliverBuilder and we add another widgetSliverPersistentHeader widget after PortfolioSliverAppBar. This widget will be filled with TabBar and its tabs.

SliverPersistentHeader has a required attribute delegate to which we define an instance of the SliverPersistentHeaderDelegateImpl class.

In the presentation layer of the application, we create a new folder delegates with the sliver_persistent_header_delegate_impl.dart file in it.

In this file, we create the SliverPersistentHeaderDelegateImpl class, which inherits from the SliverPersistentHeaderDelegate class. We define here two variables – tabBar and color. We set the color parameter to transparent color by default.

Copy to Clipboard

In the build method of this class, we return the Container widget to which we can set the color using the color attribute. And we put our tabBar widget into the child attribute.

Copy to Clipboard

From the SliverPersistentHeaderDelegate class, we inherited the maxExtent and minExtent methods, in which we return the height of our tabBar using the tabBar.preferredSize.height command.

Copy to Clipboard

MaxExtent represents the size of the header when it is not shrinking at the top of the viewport.

MinExtent is the smallest size a header can achieve when shrinking at the start of a viewport.

The last method in this class is shouldRebuild method. In our case, we return false here because we do not need to redraw the header on a change of delegate instances.

Copy to Clipboard

We go back to the portfolio_page.dart file and we import the SliverPersistentHeaderDelegateImpl class inserted into the SliverPersistentHeader delegate attribute.

We leave a default transparent color and we set only the tabBar attribute. We put a TabBar widget here and we set its color of text and icons to black using the labelColor attribute. We also set the displayed tab indicator to black using the indicatorColor attribute.

We insert our TabController into the controller attribute.

And in the tabs attribute, we insert the tab list obtained with a function map from our _pages list.

Copy to Clipboard

BottomNavigationBar

We can also use PageView and BottomNavigationBar widgets with TabBar.

We can add a Container to the bottomNavigationBar attribute of the Scaffold and set the color to blue, using the color attribute. And we put our TabBar widget from SliverPersistentHeader into the child Container attribute. For the Tab widget, we return a specific icon from the _pages list.

Copy to Clipboard

Conclusion

And with this is our eighth part of this first series of Flutter Tutorials completed and of course you can find the complete source code on the githube.