New to Rust? Grab our free Rust for Beginners eBook Get it free →
How to Create a TabBar in Flutter

When a Flutter screen has several related pages, a TabBar gives readers a way to choose which one to see. TabBar shows selectable labels, and TabBarView displays the page for the selected label.
I’ll show how to define the tabs and their pages, then how to turn off page swipes.
What is a Flutter TabBar?
A Flutter TabBar is a Material widget that displays selectable labels for switching between related pages. TabBarView shows the page for the selected label, with both widgets coordinated by a TabController.
- Keep controller length, tab count, and page count equal.
- Use NeverScrollableScrollPhysics() on TabBarView to turn off page swipes.
How Flutter tabs stay in sync
A TabBar is a Material widget that presents selectable tab labels. TabBarView displays the page for the selected tab, and a TabController keeps their selection and animation in sync.
TabBar: selectable labels
TabController: shared selection
TabBarView: selected page
For a small screen, DefaultTabController supplies that controller to descendant widgets. Its length must match both the TabBar tabs and the TabBarView children.
DefaultTabController, Scaffold, AppBar.bottom with TabBar, and a body containing TabBarView form the widget tree. The Flutter tab cookbook shows this relationship.
What you need before building tabs
Start with a Flutter project that imports the Material library. The example uses three fixed destinations in an AppBar, with one page per destination.
| Prerequisite | Reason |
|---|---|
| Flutter SDK and a runnable project | The example is a Flutter app, not a standalone Dart script |
| Material library import | TabBar and the related widgets are Material components |
| Matching list lengths | Controller length, tabs, and pages must agree |
How to create a TabBar in Flutter step by step
Build the tabs and their pages in the same widget tree so the default controller can coordinate them. The complete example uses labels to make the selected destination visible.
Step 1: Define the tabs and their pages
Use one Tab for each destination and one page widget for each TabBarView position. Matching list order makes the first tab display the first page, and so on.
<pre class="wp-block-syntaxhighlighter-code">import 'package:flutter/material.dart';
void main() {
runApp(const TabsApp());
}
class TabsApp extends StatelessWidget {
const TabsApp({super.key});
static const tabs = <Tab>[
Tab(text: 'Home', icon: Icon(Icons.home)),
Tab(text: 'Messages', icon: Icon(Icons.message)),
Tab(text: 'Settings', icon: Icon(Icons.settings)),
];
static const pages = <Widget>[
Center(child: Text('Home page')),
Center(child: Text('Messages page')),
Center(child: Text('Settings page')),
];
@override
Widget build(BuildContext context) {
return MaterialApp(
home: DefaultTabController(
length: tabs.length,
child: Scaffold(
appBar: AppBar(
title: const Text('My tabs'),
bottom: const TabBar(tabs: tabs),
),
body: const TabBarView(children: pages),
),
),
);
}
}</pre>
This is the complete screen: the controller wraps the Scaffold, the AppBar contains the tab labels, and the body contains their corresponding pages.
Step 2: Run the Flutter app
Save the code in lib/main.dart, then launch it on an available emulator or device from the project directory.
flutter run
Expected result: selecting Messages or Settings displays the matching page. Flutter and Dart are absent from the build host, so verify the sample against the official documentation when you compile it.
Fix tab count and swipe behavior
TabBar and TabBarView share one controller length, which must equal the number of tabs and pages.
| Check | Required relationship |
|---|---|
| DefaultTabController.length | Equals the number of Tab widgets |
| TabBarView.children | One child per tab, in the same order |
| TabBar ancestor | A Material widget must be an ancestor |
Set TabBarView physics to NeverScrollableScrollPhysics to keep tap selection while disabling page swipes.
body: const TabBarView(
physics: NeverScrollableScrollPhysics(),
children: pages,
),
For tabs at the bottom of a screen, this example’s AppBar.bottom placement is not the right layout. Bottom navigation is a separate design choice, while TabBar remains useful for switching between related views.
Keep the tab and page counts aligned
DefaultTabController removes manual controller setup, but it does not remove the need to keep the tab list and page list in sync. When the task needs explicit programmatic control, use a shared TabController instead.
Read the Flutter tab cookbook for the official widget walkthrough, then check the TabBar API and TabBarView API when adjusting the layout.
How do I disable swiping between Flutter tabs?
Set TabBarView.physics to const NeverScrollableScrollPhysics(). Tab labels remain selectable by tap.
Why must TabBar and TabBarView have the same number of items?
Both widgets use the same TabController index. Its length must equal the number of tabs and the number of TabBarView children.
Can I put a TabBar at the bottom of a Flutter screen?
The example here uses AppBar.bottom. A bottom tab layout needs a different scaffold placement; do not treat it as the same structure as this top AppBar example.




