unable to use ImageIcon to display image as icon flutter - flutter

I have been trying out a bottom navigation bar which has a line indicator and am using this package
https://pub.dev/packages/custom_line_indicator_bottom_navbar
I am able to see icons if I use the predefined icons. But when I tried making my own image icon, it gives me the error
The argument type 'ImageIcon' can't be assigned to the parameter type 'IconData'.
Below is the code I am using to call ImageIcon:
CustomBottomBarItems(
label: 'Account',
icon: ImageIcon(
AssetImage("images/home.png"),
color: Color(0xFF3A5A98),
),
),
when the code is written like this, it shows no error:
CustomBottomBarItems(
label: 'Leaves', icon: Icons.calendar_today_outlined),
Can someone please help me resolve this issue? Thank you

CustomBottomBarItems's icon only take IconData. You can't pass widget here.
CustomBottomBarItems(
label: 'Account',
icon: Icons.ac_unit,
)
Or switch to different widget/package like BottomNavigationBar , google_nav_bar.
Follow this snippet, replace icon with the widget
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({Key? key}) : super(key: key);
#override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
int _selectedIndex = 0;
static const TextStyle optionStyle =
TextStyle(fontSize: 30, fontWeight: FontWeight.bold);
static const List<Widget> _widgetOptions = <Widget>[
Text(
'Index 0: Home',
style: optionStyle,
),
Text(
'Index 1: Business',
style: optionStyle,
),
Text(
'Index 2: School',
style: optionStyle,
),
];
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('BottomNavigationBar Sample'),
),
body: Center(
child: _widgetOptions.elementAt(_selectedIndex),
),
bottomNavigationBar: Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
children: List.generate(
3,
(index) => Expanded(
child: Transform(
transform: Matrix4.translationValues(0, 5, 0),
child: Divider(
endIndent: 4,
indent: 4,
color: _selectedIndex == index
? Colors.red
: Colors.transparent,
),
),
)),
),
BottomNavigationBar(
showSelectedLabels: true,
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.school),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.business),
label: 'Business',
),
BottomNavigationBarItem(
icon: Icon(Icons.school),
label: 'School',
),
],
currentIndex: _selectedIndex,
selectedItemColor: Colors.amber[800],
onTap: _onItemTapped,
),
],
),
);
}
}

You may use BottomNavigationBar():
BottomNavigationBar(
items: [
BottomNavigationBarItem(
icon: Image.asset(
"assets/icons/icon",
height: 24.w,
width: 24.w,
),
label: 'label',
),
],
);

Related

Flutter : How to format the elements of the Bottom Navigation Bar and add colors and borders with radius

I want to make such a design, but I could not design the shopping cart icon in this format, how can I do it?
import 'package:flutter/material.dart';
void main() {
runApp( MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Container(),
bottomNavigationBar: BottomNavigationBar(
items: [
BottomNavigationBarItem(
icon: Icon(Icons.shopping_cart ,), label:'',
backgroundColor: Colors.red,
),
BottomNavigationBarItem(
icon: Icon(Icons.shopping_cart), label:''),
],
),
),
);
}
}
This is the code I tried to do, I couldn't format the basket icon as shown in the figma design image
Create and empty text with widget option list (_widgetOptions)
Create a BottomNavigationBarItem with empty label and in the icon widget, place container with BoxShape.circle decoration and use a custom icon of container child
Use selected and unselected item color property
In the _onItemTapped set a condition for the middle selection icon
See the full codes
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
static const String _title = 'Flutter Code Sample';
#override
Widget build(BuildContext context) {
return const MaterialApp(
title: _title,
home: MyStatefulWidget(),
);
}
}
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({super.key});
#override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
int _selectedIndex = 0;
static const TextStyle optionStyle = TextStyle(
fontSize: 30,
fontWeight: FontWeight.bold,
);
static const List<Widget> _widgetOptions = <Widget>[
Text(
'Index 0: Home',
style: optionStyle,
),
Text(
'Index 1: Business',
style: optionStyle,
),
Text(
'',
),
Text(
'Index 3: School',
style: optionStyle,
),
Text(
'Index 4: Settings',
style: optionStyle,
),
];
void _onItemTapped(int index) {
if (index != 2) {
setState(() {
_selectedIndex = index;
});
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('BottomNavigationBar Sample'),
),
body: Center(
child: _widgetOptions.elementAt(_selectedIndex),
),
bottomNavigationBar: BottomNavigationBar(
items: <BottomNavigationBarItem>[
const BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
const BottomNavigationBarItem(
icon: Icon(Icons.business),
label: 'Business',
),
BottomNavigationBarItem(
icon: Container(
height: 65,
width: 65,
decoration: const BoxDecoration(
shape: BoxShape.circle,
color: Colors.blue,
),
child: const Icon(
Icons.shopping_cart,
color: Colors.white,
),
),
label: '',
),
const BottomNavigationBarItem(
icon: Icon(Icons.school),
label: 'School',
),
const BottomNavigationBarItem(
icon: Icon(Icons.settings),
label: 'Settings',
),
],
currentIndex: _selectedIndex,
selectedItemColor: Colors.blue[800],
unselectedItemColor: Colors.black,
onTap: _onItemTapped,
),
);
}
}
I modified your code for the first BottomNavigationBarItem so it has red circular background:
BottomNavigationBarItem(
icon: Container(
height: 50,
width: 50,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.red,
),
child: Icon(
Icons.shopping_cart,
color: Colors.white,
),
),
label: '',
),
You can change the values of height, width and color to match your needs.
Also, I would recommend adding these parameters to your BottomNavigationBar to center the icons (use it only if you are going to keep all of the labels as empty strings):
showSelectedLabels: false,
showUnselectedLabels: false,

How to remove padding of BottomNavigationBarItem's "icon" property in Flutter?

There is always an unknown white space between my BottomNavigationBar and the bottom of screen. The image on the left is desired layout, but I'm only able to produce the image on the right.
Here's my code:
import 'package:flutter/material.dart';
class Wrapper extends StatefulWidget {
const Wrapper({Key? key}) : super(key: key);
#override
State<Wrapper> createState() => _WrapperState();
}
class _WrapperState extends State<Wrapper> {
final _selectedItemColor = Colors.white;
final _unselectedItemColor = const Color(0xffa3a3a3);
final _selectedBgColor = const Color(0xff1a8468);
final _unselectedBgColor = const Color(0xfff2f2f2);
int _selectedIndex = 0;
static const TextStyle optionStyle =
TextStyle(fontSize: 30, fontWeight: FontWeight.bold);
static const List<Widget> _widgetOptions = <Widget>[
Text(
'Index 0: Home',
style: optionStyle,
),
Text(
'Index 1: History',
style: optionStyle,
),
Text(
'Index 2: Lucky',
style: optionStyle,
),
Text(
'Index 3: Analysis',
style: optionStyle,
),
Text(
'Index 4: Settings',
style: optionStyle,
),
];
void _onItemTapped(int index) {
print('asdasdasd');
setState(() {
_selectedIndex = index;
});
}
Color _getBgColor(int index) =>
_selectedIndex == index ? _selectedBgColor : _unselectedBgColor;
Color _getItemColor(int index) =>
_selectedIndex == index ? _selectedItemColor : _unselectedItemColor;
Widget _buildIcon(IconData iconData, String text, int index) => Container(
width: double.infinity,
height: kToolbarHeight,
color: _getBgColor(index),
child: InkWell(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(iconData),
Text(text,
style: TextStyle(fontSize: 12, color: _getItemColor(index))),
],
),
onTap: () => _onItemTapped(index),
),
);
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
elevation: 0,
centerTitle: false,
title: const Text('Title'),
),
body: Center(
child: _widgetOptions.elementAt(_selectedIndex),
),
bottomNavigationBar: BottomNavigationBar(
selectedFontSize: 0,
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: _buildIcon(Icons.home, 'Home', 0),
label: '',
),
BottomNavigationBarItem(
icon: _buildIcon(Icons.history, 'History', 1),
label: '',
),
BottomNavigationBarItem(
icon: _buildIcon(Icons.api_outlined, 'Lucky', 2),
label: '',
),
BottomNavigationBarItem(
icon: _buildIcon(Icons.analytics, 'Analysis', 3),
label: '',
),
BottomNavigationBarItem(
icon: _buildIcon(Icons.settings, 'Settings', 4),
label: '',
),
],
currentIndex: _selectedIndex,
selectedItemColor: _selectedItemColor,
unselectedItemColor: _unselectedItemColor,
type: BottomNavigationBarType.fixed,
backgroundColor: const Color(0xfff2f2f2),
),
);
}
}
p/s: I've replaced some IconData, the outcome won't be exactly same.
May I know how do I remove the bottom blank space at the bottom? Any help is appreciated.
try this!
1 - Add this below _getItemColor
Color _getIconColor(int index) => _selectedIndex == index ? _selectedItemColor : _unselectedItemColor;
2 - Replace _buildIcon Widget
Widget _buildIcon(IconData iconData, String text, int index) => Container(
width: MediaQuery.of(context).size.width/5,
color: _getBgColor(index),
padding: EdgeInsets.only(bottom: 20,top: 10),
child: InkWell(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(iconData,color: _getIconColor(index)),
Text(text, style: TextStyle(fontSize: 12, color: _getItemColor(index))),
],
),
onTap: () => _onItemTapped(index),
),
);
3 - Wrap your Scaffold into to SafeArea
return SafeArea(
top: false,
bottom: false,
maintainBottomViewPadding: true,
minimum: EdgeInsets.only(bottom: 2.0),
child: Scaffold(code));
4 - Replace bottomNavigationBar
bottomNavigationBar: Container(
child: Wrap(
direction: Axis.horizontal,
crossAxisAlignment: WrapCrossAlignment.center,
alignment: WrapAlignment.spaceBetween,
children: [
_buildIcon(Icons.home, 'Home', 0),
_buildIcon(Icons.history, 'History', 1),
_buildIcon(Icons.api_outlined, 'Lucky', 2),
_buildIcon(Icons.analytics, 'Analysis', 3),
_buildIcon(Icons.settings, 'Settings', 4),
],
),
),
Full source code here

How to set BackGroundColor in BottomNavigationBarItem in flutter?

[enter image description here][1] Thats My Code
how to add only selected BottomNavigationBarItem background color and size in flutter. I have add my Model Screen image in below.. any one plz help me
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
backgroundColor: Color(0xffffcc2a),
showUnselectedLabels: true,
currentIndex: _currentIndex,
elevation: 20.0,
onTap: callPage,
selectedItemColor: Color(0xff3666ad),
unselectedItemColor: Color(0xff3666ad),
// this will be set when a new tab is tapped
items: [
BottomNavigationBarItem(
icon: new Icon(
Icons.ballot,
color: Color(0xff3666ad),
),
label: 'Insurance',
),
BottomNavigationBarItem(
icon: new FaIcon(
FontAwesomeIcons.car,
color: Color(0xff3666ad),
),
label: 'Motor',
),
BottomNavigationBarItem(
icon: new Icon(
Icons.medical_services,
color: Color(0xff3666ad),
),
label: ('Health'),
),
BottomNavigationBarItem(
// backgroundColor: Color(0xffffcc2a),
icon: new Icon(
Icons.flight,
color: Color(0xff3666ad),
),
label: ('Travel'),
),
BottomNavigationBarItem(
// backgroundColor: Color(0xffffcc2a),
icon: new Icon(
Icons.local_fire_department,
color: Color(0xff3666ad),
),
label: ('Fire'),
),
BottomNavigationBarItem(
// backgroundColor: Color(0xffffcc2a),
icon: FaIcon(
FontAwesomeIcons.layerGroup,
color: Color(0xff3666ad),
),
label: ('Misc'),
)
],
),
I'm using custom bottomNavigationBar for this case, play around with style and the way you desire.
class _TestWidgetState extends State<TestWidget> {
int _currentIndex = 0;
#override
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: Container(
color: Colors.green, // main background
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
NavItem(
icon: const Icon(Icons.ac_unit),
isSelected: 0 == _currentIndex,
label: "Item 1",
onTap: () {
setState(() {
_currentIndex = 0;
});
},
),
NavItem(
icon: Icon(Icons.umbrella),
isSelected: 1 == _currentIndex,
label: "Item 2",
onTap: () {
setState(() {
_currentIndex = 1;
});
},
),
],
),
),
);
}
}
class NavItem extends StatelessWidget {
const NavItem({
Key? key,
required this.icon,
required this.isSelected,
required this.onTap,
required this.label,
}) : super(key: key);
final bool isSelected;
final VoidCallback onTap;
final String label;
final Widget icon; // you may use different widget
#override
Widget build(BuildContext context) {
return Expanded(
child: (InkWell(
onTap: onTap,
child: Container(
color: isSelected
? Colors.pink
: Colors.amber, //selected background pink
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
icon,
Text("$label"),
],
),
),
)),
);
}
}

Flutter - Add a Row above Bottom Navigation Bar

I would like to know how to add a row, which upon clicking on will function like Bottom Sheet above Bottom Navigation Bar.
Like this image Example
(The darker row).
Thanks!
you can use a Scaffold property that called persistentFooterButtons, and you can add a widget to it, this is an image of the app https://i.stack.imgur.com/Tb4iA.jpg, and this is the code for making the app.
void main() async {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({Key key}) : super(key: key);
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
int _selectedIndex = 0;
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
static const TextStyle optionStyle =
TextStyle(fontSize: 30, fontWeight: FontWeight.bold);
static const List<Widget> _widgetOptions = <Widget>[
Text(
'Index 0: Home',
style: optionStyle,
),
Text(
'Index 1: Business',
style: optionStyle,
),
Text(
'Index 2: School',
style: optionStyle,
),
];
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Container(
color: Colors.white,
),
=================== this is all you need ==============================
persistentFooterButtons: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
IconButton(
iconSize: 35,
icon: Icon(Icons.play_arrow),
onPressed: null,
),
Container(child: Text("Some data over hereSome data ")),
IconButton(
icon: Icon(Icons.favorite),
onPressed: null,
)
],
)
],
=================================================
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
title: Text('Home'),
),
BottomNavigationBarItem(
icon: Icon(Icons.business),
title: Text('Business'),
),
BottomNavigationBarItem(
icon: Icon(Icons.school),
title: Text('School'),
),
],
currentIndex: _selectedIndex,
selectedItemColor: Colors.amber[800],
onTap: _onItemTapped,
),
),
);
}
}
An Expanded Widget should solve your issue. The video and documentation is at the link. It should allow for a row to be placed/pushed to the bottom of the screen so that it is "above" the navigation bar. Simply wrap your widget with an expanded widget.

Navigation rail with flutter

The material design guidelines includes a component called Navigation rail.
How to create Navigation rail with flutter?
NavigationRail
A material widget that is meant to be displayed at the left or right of an app to navigate between a small number of views, typically between three and five.
SAMPLE CODE
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
static const String _title = 'Flutter Code Sample';
#override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,
debugShowCheckedModeBanner: false,
home: HomeWidget(),
);
}
}
class HomeWidget extends StatefulWidget {
HomeWidget({Key key}) : super(key: key);
#override
_HomeWidgetState createState() => _HomeWidgetState();
}
class _HomeWidgetState extends State<HomeWidget> {
int _selectedIndex = 0;
bool showNavigationBar = false;
var list = [
HomePage(),
WalkPage(),
LocationPage(),
NotificationPage(),
SettingsPage(),
SearchPage()
];
var title = [
"HomePage",
'WalkPage',
'LocationPage',
'NotificationPage',
'SettingsPage',
'SearchPage'
];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title[_selectedIndex]),
centerTitle: false,
leading: IconButton(
icon: Icon(
Icons.menu,
color: Colors.white,
),
onPressed: () {
setState(() {
showNavigationBar = !showNavigationBar;
});
}),
),
body: Container(
child: SafeArea(
child: Stack(
children: <Widget>[
list[_selectedIndex],
Positioned(
top: 0,
left: 0,
child: Visibility(
visible: showNavigationBar,
child: Container(
height: MediaQuery.of(context).size.height,
child: NavigationRail(
selectedIndex: _selectedIndex,
elevation: 10,
backgroundColor: Colors.white,
leading: Container(
child: Center(child: Text('leading')),
),
trailing: Container(
child: Center(child: Text('trailing')),
),
selectedIconTheme: IconThemeData(color: Colors.purple, size: 30),
unselectedIconTheme: IconThemeData(color: Colors.grey, size: 20),
selectedLabelTextStyle:
TextStyle(color: Colors.purple, fontWeight: FontWeight.bold),
unselectedLabelTextStyle:
TextStyle(color: Colors.grey, fontWeight: FontWeight.normal),
onDestinationSelected: (int index) {
setState(() {
_selectedIndex = index;
showNavigationBar = !showNavigationBar;
});
},
labelType: NavigationRailLabelType.none,
destinations: [
NavigationRailDestination(
icon: Icon(Icons.home),
selectedIcon: Icon(Icons.home),
label: Text('Home'),
),
NavigationRailDestination(
icon: Icon(Icons.directions_walk),
selectedIcon: Icon(Icons.directions_walk),
label: Text('Walk'),
),
NavigationRailDestination(
icon: Icon(Icons.location_on),
selectedIcon: Icon(Icons.location_on),
label: Text('Location'),
),
NavigationRailDestination(
icon: Icon(Icons.notifications),
selectedIcon: Icon(Icons.notifications),
label: Text('Notifications'),
),
NavigationRailDestination(
icon: Icon(Icons.settings),
selectedIcon: Icon(Icons.settings),
label: Text('Settings'),
),
NavigationRailDestination(
icon: Icon(Icons.search),
selectedIcon: Icon(Icons.search),
label: Text('Search'),
),
],
),
),
),
),
],
)),
),
);
}
}
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
color: Colors.red,
child: Center(
child: Text('Home Page',
style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 20.0))),
);
}
}
class WalkPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
color: Colors.blue,
child: Center(
child: Text('Walk Page',
style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 20.0))),
);
}
}
class LocationPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
color: Colors.orange,
child: Center(
child: Text('Location Page',
style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 20.0))),
);
}
}
class NotificationPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
color: Colors.green,
child: Center(
child: Text('Notification Page',
style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 20.0))),
);
}
}
class SettingsPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
color: Colors.amber,
child: Center(
child: Text('Settings Page',
style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 20.0))),
);
}
}
class SearchPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
color: Colors.teal,
child: Center(
child: Text('Search Page',
style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 20.0))),
);
}
}
Let us understand some of its important properties
selectedIndex - The index into destinations for the current selected NavigationRailDestination.
selectedIconTheme - The visual properties of the icon in the selected destination.
unselectedIconTheme
- The visual properties of the icon in the unselected destination.
selectedLabelTextStyle - The TextStyle of a destination's label when it is selected.
unselectedLabelTextStyle - The TextStyle of a destination's label when it is unselected.
backgroundColor - Sets the color of the container that holds all of the NavigationRail's contents.
leading - The leading widget in the rail that is placed above the destinations
trailing - The trailing widget in the rail that is placed below the destinations.
labelType
labelType: NavigationRailLabelType.all,
labelType: NavigationRailLabelType.selected,
labelType: NavigationRailLabelType.none,
OUTPUT
For more information please read the documentation of NavigationRail
You can test live demo here on NavigationRail demo
The latest version of Flutter 1.17 includes a built in NavigationRail component.
What is Navigation rail?
The rail is a side navigation component that displays three to seven app destinations and, optionally, a Floating Action Button. Each destination is represented by an icon and a text label. The rail can function on its own at larger screen sizes, such as desktop and tablet. When users transition between screen sizes and devices, the rail can also complement other navigation components, such as bottom navigation.
Example
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
/// This Widget is the main application widget.
class MyApp extends StatelessWidget {
static const String _title = 'Flutter Code Sample';
#override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,
home: MyStatefulWidget(),
);
}
}
class MyStatefulWidget extends StatefulWidget {
MyStatefulWidget({Key key}) : super(key: key);
#override
_MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
int _selectedIndex = 0;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Row(
children: <Widget>[
NavigationRail(
selectedIndex: _selectedIndex,
onDestinationSelected: (int index) {
setState(() {
_selectedIndex = index;
});
},
labelType: NavigationRailLabelType.selected,
destinations: [
NavigationRailDestination(
icon: Icon(Icons.favorite_border),
selectedIcon: Icon(Icons.favorite),
label: Text('First'),
),
NavigationRailDestination(
icon: Icon(Icons.bookmark_border),
selectedIcon: Icon(Icons.book),
label: Text('Second'),
),
NavigationRailDestination(
icon: Icon(Icons.star_border),
selectedIcon: Icon(Icons.star),
label: Text('Third'),
),
],
),
VerticalDivider(thickness: 1, width: 1),
// This is the main content.
Expanded(
child: Center(
child: Text('selectedIndex: $_selectedIndex'),
),
)
],
),
);
}
}
Find a live demo here.
Here is the official documentation.
It was released on the 7th of May, 2020 with the Flutter 1.17 release. A quick search for "navigation rail flutter" would have done the trick.
The documentation includes a live demo and example code.
int _selectedIndex = 0;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Row(
children: <Widget>[
NavigationRail(
selectedIndex: _selectedIndex,
onDestinationSelected: (int index) {
setState(() {
_selectedIndex = index;
});
},
labelType: NavigationRailLabelType.selected,
destinations: [
NavigationRailDestination(
icon: Icon(Icons.favorite_border),
selectedIcon: Icon(Icons.favorite),
label: Text('First'),
),
NavigationRailDestination(
icon: Icon(Icons.bookmark_border),
selectedIcon: Icon(Icons.book),
label: Text('Second'),
),
NavigationRailDestination(
icon: Icon(Icons.star_border),
selectedIcon: Icon(Icons.star),
label: Text('Third'),
),
],
),
VerticalDivider(thickness: 1, width: 1),
// This is the main content.
Expanded(
child: Center(
child: Text('selectedIndex: $_selectedIndex'),
),
)
],
),
);
}
To upgrade, run flutter upgrade, which will download the latest version from github.
Note: The navigation rail is meant for layouts with wide viewports, such as a desktop web or tablet landscape layout. For smaller layouts, like mobile portrait, a BottomNavigationBar should be used instead.
int _index = 0;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Row(
children: <Widget>[
NavigationRail(
selectedIndex: _index,
onDestinationSelected: (index) => setState(() => _index = index),
extended: true,
destinations: [
NavigationRailDestination(
icon: Icon(Icons.favorite_border),
label: Text('First'),
),
NavigationRailDestination(
icon: Icon(Icons.bookmark_border),
label: Text('Second'),
),
NavigationRailDestination(
icon: Icon(Icons.star_border),
label: Text('Third'),
),
],
),
// This is the main content.
Expanded(child: Center(child: Text('Index: $_index')))
],
),
);
}
NavigationRail looks neat. But I noticed there is no way to save the widget state so it always gets recreated. Not even AutomaticKeepAliveClientMixin works.