Creating an App’s Navigation
Navigator.push, Navigator.pop and
Navigator.pushNamed,
In Flutter, the Navigator widget helps to move between screens in an app.
Think of Navigator as a "stack" of pages, where each new page you open is
placed on top of the stack, and you can move back to previous pages by
removing the top one.
To go to a new page: Use Navigator.push or Navigator.pushNamed.
This lets you move forward to a new screen and even send data to it.
To go back to a previous page: Use Navigator.pop. You can also use pop
to send data back to the previous screen.
Setting fullscreenDialog: true adds a "close" button at the top left on iOS. The
page slides up from the bottom on both iOS and Android.
To close a page, use Navigator.pop(context);. You can also pass a value back to
the previous page by adding a second argument, like this:
Navigator.pop(context, 'Done');
How Navigator.push Works
1. Pushes a New Screen (Route) Onto the Stack:
o When we use Navigator.push, you add a new route to the
stack. The topmost route (the newly pushed screen) becomes the
active screen, and the previous route is still on the stack but
hidden behind the new one.
2. Takes Two Required Arguments:
o context: The BuildContext of the widget that initiates the
navigation.
o route: A Route object that defines the new page you want to
navigate to.
3. Using MaterialPageRoute:
o Typically, you use MaterialPageRoute to create the new
route because it provides platform-specific transitions for both iOS
and Android.
o MaterialPageRoute has a builder parameter where you
specify the widget (new screen) you want to navigate to.
Example for Navigator.push and Navigator.pop.
- Navigation from first screen to second screen
Second screen
Navigation using pushNamed
step 1: main.dart:
create a name reference in main.dart
Step 2: Use Navigator.pushNamed
Hero Animation
The Hero widget in Flutter allows to create a smooth animation between two
pages (screens) when navigating. It gives the effect of a specific widget, like an
image or button, "flying" or "transitioning" from one page to another. This type
of animation is called a shared element transition.
1. Working:
o A widget can move from one screen to another during navigation.
For example, an image on one page grows and transitions
smoothly to another page.
2. Key Idea:
o The Hero widget works by "matching" a widget on the first page
with a widget on the second page. Both widgets must have the
same tag property, which acts as an identifier.
3. Reversing Animation:
o When you navigate back to the original page, the animation
reverses, and the widget smoothly returns to its original size and
position.
4. No Custom Animation Code Needed:
o The Hero widget handles the animation for you automatically. You
just need to wrap the widget you want to animate in a Hero
widget and give it a unique tag.
Example:
Hero Animation 2:
Hero Animation 2:
BottomNavigationBar
BottomNavigationBar is a Flutter widget that provides a navigation bar at the
bottom of the screen, often used to switch between different pages or views
in an app. It follows Material Design guidelines, making it a user-friendly way
to navigate an app.
BottomNavigationBar Properties
items: A list of BottomNavigationBarItem widgets that define the
navigation options (icon and label).
currentIndex: The index of the currently selected item (used to highlight
the active item).
onTap: A callback function that is triggered when an item is tapped. It
receives the index of the tapped item, which you can use to update the
state.
selectedItemColor and unselectedItemColor: Colors for selected and
unselected items, respectively.
backgroundColor: Sets the background color of the navigation bar.
type: Determines the layout of the bar (e.g.,
BottomNavigationBarType.fixed or BottomNavigationBarType.shifting).
How They Work Together
BottomNavigationBar holds a list of BottomNavigationBarItems.
Each BottomNavigationBarItem represents an option in the navigation
bar.
The onTap callback allows to respond to user input by switching pages.
Example of Bottom Navigation Bar:
import 'package:flutter/material.dart';
class BottomNavBarExample extends StatefulWidget {
@override
_BottomNavBarExampleState createState() => _BottomNavBarExampleState();
}
class _BottomNavBarExampleState extends State<BottomNavBarExample> {
// Current index to track the selected tab
int _selectedIndex = 0;
// List of screens to display based on selected index
final List<Widget> screens = [
HomeScreen(),
SearchScreen(),
ProfileScreen(),
];
// Function to handle tab selection
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index; // Update selected index
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Bottom Navigation Bar Example"),
),
body: screens[_selectedIndex], // Display selected screen
bottomNavigationBar: BottomNavigationBar(
currentIndex: _selectedIndex, // Highlight selected tab
onTap: _onItemTapped, // Handle tap on tab
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
title: Text('Home'), // Use 'title' for text in Flutter 1.20.2
),
BottomNavigationBarItem(
icon: Icon(Icons.search),
title: Text('Search'), // Use 'title' for text in Flutter 1.20.2
),
BottomNavigationBarItem(
icon: Icon(Icons.account_circle),
title: Text('Profile'), // Use 'title' for text in Flutter 1.20.2
),
],
),
);
}
}
Gesture Detector
The GestureDetector widget in Flutter is used to detect and respond to
user interactions, like taps, swipes, double taps, long presses, and other
gestures on a widget. It acts as an invisible listener for gestures on the widget
it's wrapped around.
BottomAppBar
The BottomAppBar widget is used to create a bar at the bottom of the
screen. Unlike the BottomNavigationBar, it can have a notch that appears
when we place a FloatingActionButton on the bar and set the shape to a
NotchedShape, like CircularNotchedRectangle.
Steps to Create a BottomAppBar with a Notch:
1. Use the BottomAppBar Widget in the bottomNavigationBar property of
the Scaffold.
2. Add a Shape: Set the shape property of BottomAppBar to
CircularNotchedRectangle().
3. Place a FloatingActionButton:
o Use the floatingActionButton property of Scaffold.
o Set the position using floatingActionButtonLocation, like
FloatingActionButtonLocation.endDocked or centerDocked.
4. Add Icons or Widgets in the BottomAppBar for additional actions.
Example:
import 'package:flutter/material.dart';
class BottomAppBarExample extends StatefulWidget {
@override
_BottomAppBarExampleState createState() => _BottomAppBarExampleState();
}
class _BottomAppBarExampleState extends State<BottomAppBarExample> {
int _selectedIndex = 0;
// List of screens to navigate to
final List<Widget> _screens = [
HomeScreen(),
SearchScreen(),
ProfileScreen(),
];
// Update the selected index
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('BottomAppBar Navigation'),
),
body: _screens[_selectedIndex], // Display selected screen
// BottomAppBar with navigation icons
bottomNavigationBar: BottomAppBar(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
IconButton(
icon: Icon(Icons.home),
onPressed: () => _onItemTapped(0),
),
IconButton(
icon: Icon(Icons.search),
onPressed: () => _onItemTapped(1),
),
IconButton(
icon: Icon(Icons.account_circle),
onPressed: () => _onItemTapped(2),
),
],
),
),
);
}
}
Explanation of the difference between Bottom Navigation Bar and Bottom
App Bar:
Bottom Navigation Bar:
It’s a predefined widget that lets users switch between different screens of the
app.
Main Use: You use it to show 3 to 5 main sections of your app, like Home,
Search, and Profile.
Fixed Layout: It has a simple layout with icons and labels for navigation.
Use Case: Ideal for simple apps where you need a quick and easy way to switch
between major sections.
Bottom App Bar:
It’s a more flexible widget that can contain any widgets, like buttons or icons,
and can be customized to fit your needs.
Main Use: It is used to hold custom content at the bottom of the screen, such
as a Floating Action Button (FAB) or other widgets.
Custom Layout: You can place any widget inside it, allowing for more complex
designs.
Use Case: Ideal for apps where you need more control over the bottom layout,
like placing additional actions or using a floating button.
Key Difference:
Bottom Navigation Bar is for simple navigation between views.
Bottom App Bar is for customizing the bottom part of your app with more
actions or elements.
Example:
Bottom Navigation Bar: App with tabs for Home, Search, Profile.
Bottom App Bar: App with a floating action button for adding new items and
other custom icons for extra actions.
USING THE TABBAR AND TABBARVIEW
TabBar:
The TabBar widget displays a row of tabs (like buttons) that the user can
select to switch between different views or pages.
You add tabs using the Tab widget. Each tab is represented by a label,
and the selected tab is shown with a line under it.
TabBarView:
The TabBarView widget shows the content of the selected tab.
When a tab is selected, TabBarView displays the related page or content
for that tab.
You can switch between tabs by tapping on the tabs or swiping left and
right.
TabController:
Both the TabBar and TabBarView widgets need a TabController to sync
the tab selection.
The TabController makes sure that when a tab is selected, the correct
content is shown in TabBarView.
You use the SingleTickerProviderStateMixin to help manage the
TabController for smooth transitions between tabs.
Example:
TabBar can be placed at the bottom of the screen using the
bottomNavigationBar property.
When you select a tab in the TabBar, the corresponding page in TabBarView is
shown.
In short, TabBar is used for navigation between different sections, and
TabBarView displays the content related to the selected tab. You need a
TabController to make sure they work together properly.
Example Program
import 'package:flutter/material.dart';
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with
SingleTickerProviderStateMixin {
// Create a TabController
TabController tabController;
@override
void initState() {
super.initState();
// Initialize the TabController with 3 tabs
tabController = TabController(length: 3, vsync: this);
}
@override
void dispose() {
// Dispose of the TabController when done
tabController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('TabBar and TabBarView Example'),
bottom: TabBar(
controller: tabController,
tabs: [
Tab(text: 'Tab 1'),
Tab(text: 'Tab 2'),
Tab(text: 'Tab 3'),
],
),
),
body: TabBarView(
controller: tabController,
children: [
// Content for Tab 1
Center(
child: Text('Content for Tab 1'),
),
// Content for Tab 2
Center(
child: Text('Content for Tab 2'),
),
// Content for Tab 3
Center(
child: Text('Content for Tab 3'),
),
],
),
);
}
}
Using the Drawer and ListView.
In Flutter, the Drawer is a material design panel that slides in from the left or
right edge of the screen, typically used for app navigation. It provides an easy
way to organize and access multiple sections or features of an app without
taking up too much space on the main screen.
The ListView widget is commonly used inside the Drawer to show a list of
items, such as links to different sections or pages in the app. It’s a scrollable list
that allows you to add as many items as needed.
What is ListView?
The ListView widget is a scrollable list of widgets arranged vertically. It is
commonly used in scenarios where there are many items to display, like in a
Drawer menu.
How to Use Drawer with ListView?
To create a navigation menu, we place a ListView inside the Drawer. Each item
in the ListView can be a button, a link, or any widget that the user can interact
with to navigate to a different part of the app.
Example:
import 'package:flutter/material.dart';
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Drawer & ListView Example')),
drawer: Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
// Drawer header (optional)
UserAccountsDrawerHeader(
currentAccountPicture: CircleAvatar(
backgroundImage: AssetImage('assets/profile_pic.jpg'),
),
accountName: Text('KLE'),
accountEmail: Text('
[email protected]'),
decoration: BoxDecoration(
color: Colors.blue,
),
),
// List items inside the Drawer
ListTile(
leading: Icon(Icons.home),
title: Text('Home'),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context)=> HomeScreen(),
)
);
// Navigate to home
},
),
ListTile(
leading: Icon(Icons.search),
title: Text('Settings'),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context)=> SearchScreen(),
)
);
// Navigate to Search SCreen
},
),
ListTile(
leading: Icon(Icons.account_circle),
title: Text('About'),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context)=> ProfileScreen(),
)
);
// Navigate to Profile
},
),
],
),
),
body: Center(child: Text('Content of the screen')),
),
);
}
}