Gravid Banner

Styling Tab Bar in Flutter

Recently I decided to add a default tab bar to my app in flutter. This is relatively straightforward to achieve using the following

  @override
  Widget build(BuildContext context) {
    return DefaultTabController (
      length: 2,
      child: Scaffold(
        appBar: AppBar(
          title: Text("Tab Bar Test"),
          bottom: TabBar(
            tabs:[
              Tab(text: "First"),
              Tab(text: "Second"),
            ]
          )
        ),  
      body: TabBarView(
        children: [
          Padding(
            padding: EdgeInsets.all(18.0),
            child: Text ("Page One")
          ),
        Padding(
          padding: EdgeInsets.all(18.0),
          child: Text("Page Two"),
          )
        )
      )
    );
  }
Dart

And this yields a tab bar with two pages which looks like this:

Following on from my posts about using Themes in Flutter, we can now start to style the tab bar using the Theme parameter under MaterialApp. In the following snippet the indicator size changes the underline for the selected tab to span the whole width of the tab, whilst the label style and colors change the font styling of the tab label.

return MaterialApp(
  theme: ThemeData(
    tabBarTheme: const TabBarThemeData(
      indicatorSize: TabBarIndicatorSize.tab,
      labelStyle: TextStyle(fontWeight: FontWeight.bold),
      unselectedLabelStyle: TextStyle(fontWeight: FontWeight.bold),    
      labelColor: Colors.indigo,
      unselectedLabelColor: Colors.grey,
    ),
  ),
);
Dart

Now our tab layout looks as follows:

Using the theme to also change the background color of our AppBar gives us an issue. Because the tab bar is part of the AppBar, it unhelpfully takes on the same background color.

return MaterialApp(
  theme: ThemeData(
    appBarTheme: const AppBarTheme(
      backgroundColor: Colors.indigo,
      foregroundColor: Colors.white,
    ),
  tabBarTheme: const TabBarThemeData( 
Dart

Tab Bar does not have a background color option, and as it is a preffered width widget we can’t just wrap it in a container. A simple option order (via this stackoverflow) is to create a custom class which implements the tab bar. For example:

class ColoredTabBar extends ColoredBox implements PreferredSizeWidget {
  const ColoredTabBar({required this.color, required this.tabBar}) :
    super(color: color, child: tabBar);

  @override
  final Color color;
  final TabBar tabBar;

  @override
  Size get preferredSize => tabBar!.preferredSize;
}
Dart

And replace our original tab bar with the new colored one

        title: Text("Tab Bar Test"),
        bottom: ColoredTabBar(color: Colors.white,
          tabBar: TabBar(
            tabs:[
              Tab(text: "First"),
              Tab(text: "Second"),
            ]
          )
        ),
Dart

So now it looks like this:

The final thing that I wanted to achieve was to make the underline of the selected tab a bit thicker. This can be achieved using the indicator parameter of the tab bar.

          tabBar: TabBar(
            indicator: UnderlineTabIndicator(
              borderSide: BorderSide(width: 6.0, color: Colors.indigo),
            ),
            tabs:[
Dart

The final tab bar looks like this:


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *