Flutter TabBar is one of the most essential navigation components in Flutter development. When building Flutter applications, implementing a Flutter TabBar provides an intuitive way for users to navigate between different sections of your app. In this comprehensive guide, we’ll explore everything you need to know about Flutter TabBar implementation, from basic setup to advanced customizations.
The Flutter TabBar widget works seamlessly with TabBarView to create a complete tabbed interface. Whether you’re building a social media app, e-commerce platform, or any multi-section application, mastering Flutter TabBar is crucial for creating professional user interfaces.
Flutter TabBar operates within a complex widget hierarchy that requires careful implementation. The primary components involved in Flutter TabBar implementation include TabController, TabBar, and TabBarView widgets. This architecture ensures smooth coordination between tab selection and content display.
The TabController serves as the brain of your Flutter TabBar system, managing the currently selected tab and coordinating animations. When implementing Flutter TabBar, the TabController automatically handles tab switching logic and maintains synchronization between the tab headers and their corresponding content.
class _MyTabBarState extends State<MyTabBar> with SingleTickerProviderStateMixin {
late TabController _tabController;
@override
void initState() {
super.initState();
_tabController = TabController(length: 3, vsync: this);
}
}
The length property in Flutter TabBar determines how many tabs your interface will contain. This property must match the number of Tab widgets you provide and the number of pages in your TabBarView.
TabController(length: 4, vsync: this)
The vsync property synchronizes Flutter TabBar animations with the screen refresh rate. Always use this
when your widget extends SingleTickerProviderStateMixin or TickerProviderStateMixin.
TabController(length: 3, vsync: this)
Flutter TabBar allows you to specify which tab should be selected initially through the initialIndex property. This is particularly useful when you want users to start on a specific tab rather than the default first tab.
TabController(length: 3, vsync: this, initialIndex: 1)
The indicator property in Flutter TabBar controls the appearance of the selection indicator beneath active tabs. Flutter provides several built-in indicators, and you can create custom indicators for unique designs.
TabBar(
indicator: BoxDecoration(
border: Border(bottom: BorderSide(color: Colors.blue, width: 3))
),
tabs: tabs,
)
Flutter TabBar indicatorColor property allows you to customize the color of the default underline indicator. This simple property provides quick styling without creating custom decorations.
TabBar(
indicatorColor: Colors.red,
tabs: tabs,
)
The indicatorWeight property in Flutter TabBar controls the thickness of the default indicator line. Adjust this value to make your indicator more or less prominent.
TabBar(
indicatorWeight: 4.0,
tabs: tabs,
)
Flutter TabBar provides separate color controls for active and inactive tab labels through labelColor and unselectedLabelColor properties.
TabBar(
labelColor: Colors.blue,
unselectedLabelColor: Colors.grey,
tabs: tabs,
)
The simplest Flutter TabBar implementation uses Tab widgets with text labels. These provide clear navigation options for users.
Tab(text: "Home")
Tab(text: "Profile")
Tab(text: "Settings")
Flutter TabBar supports icon-based tabs for more visual navigation. Icons can be more intuitive than text for certain application types.
Tab(icon: Icon(Icons.home))
Tab(icon: Icon(Icons.person))
Tab(icon: Icon(Icons.settings))
Combining text and icons in Flutter TabBar tabs provides the best of both worlds - visual appeal and clear labeling.
Tab(icon: Icon(Icons.home), text: "Home")
Tab(icon: Icon(Icons.person), text: "Profile")
Tab(icon: Icon(Icons.settings), text: "Settings")
When your Flutter TabBar contains many tabs, the isScrollable property enables horizontal scrolling instead of cramming all tabs into the available space.
TabBar(
isScrollable: true,
tabs: tabs,
)
Flutter TabBar tabAlignment property controls how tabs are positioned when isScrollable is true. Options include start, center, and fill.
TabBar(
isScrollable: true,
tabAlignment: TabAlignment.start,
tabs: tabs,
)
The onTap property in Flutter TabBar allows you to execute custom logic when users select tabs. This is useful for analytics, state management, or triggering specific actions.
TabBar(
onTap: (index) {
print("Selected tab: $index");
// Custom logic here
},
tabs: tabs,
)
Here’s a comprehensive Flutter TabBar example demonstrating all the concepts we’ve covered:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter TabBar Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyTabBarDemo(),
);
}
}
class MyTabBarDemo extends StatefulWidget {
@override
_MyTabBarDemoState createState() => _MyTabBarDemoState();
}
class _MyTabBarDemoState extends State<MyTabBarDemo> with SingleTickerProviderStateMixin {
late TabController _tabController;
@override
void initState() {
super.initState();
_tabController = TabController(
length: 4,
vsync: this,
initialIndex: 0
);
}
@override
void dispose() {
_tabController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter TabBar Example'),
backgroundColor: Colors.blue,
foregroundColor: Colors.white,
bottom: TabBar(
controller: _tabController,
indicatorColor: Colors.white,
indicatorWeight: 3.0,
labelColor: Colors.white,
unselectedLabelColor: Colors.white70,
isScrollable: false,
onTap: (index) {
print("Tab $index selected");
},
tabs: [
Tab(
icon: Icon(Icons.home),
text: "Home",
),
Tab(
icon: Icon(Icons.search),
text: "Search",
),
Tab(
icon: Icon(Icons.favorite),
text: "Favorites",
),
Tab(
icon: Icon(Icons.person),
text: "Profile",
),
],
),
),
body: TabBarView(
controller: _tabController,
children: [
// Home Tab Content
Container(
padding: EdgeInsets.all(20),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.home, size: 100, color: Colors.blue),
SizedBox(height: 20),
Text(
"Welcome to Home",
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
SizedBox(height: 10),
Text(
"This is the home tab content. You can add any widgets here.",
textAlign: TextAlign.center,
style: TextStyle(fontSize: 16, color: Colors.grey[600]),
),
],
),
),
// Search Tab Content
Container(
padding: EdgeInsets.all(20),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.search, size: 100, color: Colors.green),
SizedBox(height: 20),
Text(
"Search Section",
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
SizedBox(height: 10),
TextField(
decoration: InputDecoration(
hintText: "Type something to search...",
border: OutlineInputBorder(),
prefixIcon: Icon(Icons.search),
),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Search functionality implemented!")),
);
},
child: Text("Search"),
),
],
),
),
// Favorites Tab Content
Container(
padding: EdgeInsets.all(20),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.favorite, size: 100, color: Colors.red),
SizedBox(height: 20),
Text(
"Your Favorites",
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
SizedBox(height: 20),
Expanded(
child: ListView.builder(
itemCount: 5,
itemBuilder: (context, index) {
return Card(
margin: EdgeInsets.symmetric(vertical: 5),
child: ListTile(
leading: Icon(Icons.favorite, color: Colors.red),
title: Text("Favorite Item ${index + 1}"),
subtitle: Text("This is your favorite item number ${index + 1}"),
trailing: IconButton(
icon: Icon(Icons.delete),
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Item ${index + 1} removed from favorites")),
);
},
),
),
);
},
),
),
],
),
),
// Profile Tab Content
Container(
padding: EdgeInsets.all(20),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircleAvatar(
radius: 50,
backgroundColor: Colors.purple,
child: Icon(Icons.person, size: 60, color: Colors.white),
),
SizedBox(height: 20),
Text(
"John Doe",
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
SizedBox(height: 10),
Text(
"Flutter Developer",
style: TextStyle(fontSize: 16, color: Colors.grey[600]),
),
SizedBox(height: 30),
Card(
child: Padding(
padding: EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(Icons.email, color: Colors.blue),
SizedBox(width: 10),
Text("john.doe@example.com"),
],
),
SizedBox(height: 10),
Row(
children: [
Icon(Icons.phone, color: Colors.green),
SizedBox(width: 10),
Text("+1 234 567 8900"),
],
),
SizedBox(height: 10),
Row(
children: [
Icon(Icons.location_on, color: Colors.red),
SizedBox(width: 10),
Text("New York, USA"),
],
),
],
),
),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Profile updated successfully!")),
);
},
child: Text("Edit Profile"),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.purple,
foregroundColor: Colors.white,
),
),
],
),
),
],
),
);
}
}
This complete Flutter TabBar example demonstrates a fully functional tabbed interface with custom styling, event handling, and rich content in each tab. The implementation includes proper controller management, custom indicators, and interactive elements within each tab’s content area.
The example showcases various Flutter TabBar features including icon and text combinations, custom colors, event handling through onTap callbacks, and proper resource disposal. Each tab contains unique content demonstrating how Flutter TabBar can be used to organize different sections of your application effectively.