Trying to add a pageview controller without success....completely new at this - flutter

I am completely new at coding and of course I am trying to tackle one of the largest projects I can think of.... anyways. I am running into a huge wall when it comes to my current stage of coding. I have a defaultTabController at the upper portion of the screen with the functionality to switch in between two tabs. I would also like to have a bottomNavigationBar at the bottom of the application with 5 buttons that navigate to additional pages.
I have been attempting to add this code PageView(controller: _pageController, children: <Widget>[],) to the body of my code, yet I am either getting an overload of errors or only the top or bottom nav bars are active. If someone could show me what I'm doing wrong, I would be so grateful!
class HomeScreen extends StatefulWidget {
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
int _currentTab = 0;
PageController _pageController;
#override
void initState() {
super.initState();
_pageController = PageController();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: DefaultTabController(
length: 2,
child: Scaffold(
extendBodyBehindAppBar: true,
extendBody: true,
appBar: AppBar(
backgroundColor:
Colors.grey.withOpacity(0.5),
title: Text(
'TREBLE',
style: TextStyle(
color: Colors.black,
fontFamily: "treblefont",
fontSize: (33.0)
),
),
bottom: TabBar(
tabs: <Widget>[
Tab(text: "Following"),
Tab(text: "trending"),
],
)
),
body:
TabBarView(
children: <Widget>[
FeedScreen(),
TrendingScreen(),
],
),
bottomNavigationBar: CupertinoTabBar(
currentIndex: _currentTab,
onTap: (int index) {
setState(() {
_currentTab = index;
});
},
activeColor: Colors.black,
backgroundColor: Colors.white.withOpacity(0.5),
items: [
BottomNavigationBarItem(
icon: Icon(
Icons.home,
size: 32.0,
),
),
BottomNavigationBarItem(
icon: Icon(
Icons.search,
size: 32.0,
),
),
BottomNavigationBarItem(
icon: Icon(
Icons.camera_enhance,
size: 32.0,
),
),
BottomNavigationBarItem(
icon: Icon(
Icons.notifications,
size: 32.0,
),
),
BottomNavigationBarItem(
icon: Icon(
Icons.account_circle,
size: 32.0,
),
),
],
),
),
),
);
}
}
I attempt to insert the code here:
)
),
body:
PageView(controller: _pageController, children: <Widget>[],)
TabBarView(
children: <Widget>[
FeedScreen(),
TrendingScreen(),
],
),
bottomNavigationBar: CupertinoTabBar(
currentIndex: _currentTab,
onTap: (int index) {
setState(() {
_currentTab = index;
});
},
line of code screenshot
Specific error readout screenshot

Related

Navigating Navigation Bar

So I'm working on project with flutter. First I want to know if using a bottom Navigation Bar is better than creating a container for it. Now my question, how do I navigate to a page by using this bottom Navigation bar? Like should I build an entire page and bottom navigation bar for each one? OR Can I build everything in one place ?
This a part of it
void main() => runApp(MyApp());
class ProfilePage extends StatefulWidget {
#override
State<ProfilePage> createState() => _ProfilePageState();
}
class _ProfilePageState extends State<ProfilePage> {
int _selectedIndex = 0;
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: Text('HOME'),
centerTitle: true,
backgroundColor: Colors.green[900],
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
Navigator.pop(context);
},
),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [],
),
bottomNavigationBar: BottomNavigationBar(
backgroundColor: Colors.green[900],
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(
Icons.home,
),
label: 'Home',
backgroundColor: Colors.green[900],
),
BottomNavigationBarItem(
icon: Icon(
Icons.calendar_today,
),
label: 'Days',
backgroundColor: Colors.green[900],
),
BottomNavigationBarItem(
icon: Icon(
Icons.local_activity,
),
label: 'Activity',
backgroundColor: Colors.green[900],
),
BottomNavigationBarItem(
icon: Icon(
Icons.settings,
),
label: 'Settings',
backgroundColor: Colors.green[900],
),
],
currentIndex: _selectedIndex,
selectedItemColor: Colors.white,
onTap: _onItemTapped,
),
),
);
}
}
This is how it looks but don't know how to navigate between screens.
you PageView class for change pages
Change Column to Pageview
final PageController controller = PageController();
return PageView(
/// [PageView.scrollDirection] defaults to [Axis.horizontal].
/// Use [Axis.vertical] to scroll vertically.`enter code here`
controller: controller,
children: const <Widget>[
Center(
child: Text('First Page'),
),
Center(
child: Text('Second Page'),
),
Center(
child: Text('Third Page'),
)
],
);
}
change in your method
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
controller.jumpToPage(index);
});
}
You don't need to create a BnB for each screen, you can create a navbar on the main screen
and in the build method return the corresponding page, based on the selected index.

bottomNavigationBar OnTap does not trigger for navigate to another page

#override
void initState() {
super.initState();
}
int selectedPage = 0;
void changePage(int index) {
setState(() {
selectedPage = index;
});
}
bottomNavigationBar: BottomNavigationBar(
showUnselectedLabels: true,
currentIndex: selectedPage,
onTap: showPage,
items: const [
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Main',
backgroundColor: Colors.blue),
BottomNavigationBarItem(
icon: Icon(Icons.category_outlined),
label: 'Category',
backgroundColor: Colors.blue),
BottomNavigationBarItem(
icon: Icon(Icons.book_online),
label: 'Photos',
backgroundColor: Colors.blue),
BottomNavigationBarItem(
icon: Icon(Icons.video_call),
label: 'Video',
backgroundColor: Colors.blue),
],
Widget showPage(int selectedPage) {
if (selectedPage == 0) {
return NewsViewDetail(id: '0');
} else if (selectedPage == 1) {
return NewsLoading(text: 'load');
}
return NewsLoading(text: '1');
}
When I tap first or second item on the there is no reaction from UI. It seems onTap does not navigate to different pages.
Could you please help me why this code is not working?
Edit: I think the problem causing Scaffold body. Current Scaffold body is:
body: TabBarView(
children: [
for (final tab in filteredList)
NewsView(
id: tab.id!,
),
],
),
How can I integrate showPage(_selectedIndex), into Scaffold Body without hurt the TabbarView?
here is the TabBarController
return DefaultTabController(
// length: snapshot.data!.data!.length,
length: filteredList.length,
child: Scaffold(
appBar: AppBar(
backgroundColor: (Colors.white),
iconTheme: const IconThemeData(color: Colors.black),
title: Transform.translate(
offset: const Offset(-24.0, 0.0),
child: Image.asset("assets/images/lo.png",
fit: BoxFit.contain, height: 22),
),
bottom: PreferredSize(
preferredSize: const Size.fromHeight(30.00),
child: ColoredBox(
color: Colors.white,
child: TabBar(
labelColor: Colors.purple[100],
indicatorColor: Colors.purple,
isScrollable: true,
labelPadding:
const EdgeInsets.symmetric(horizontal: 8.0),
tabs: tabs),
),
),
),
```
Check it, it will be helped you to solve your solution
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyNavigationBar(),
);
}
}
class MyNavigationBar extends StatefulWidget {
MyNavigationBar({Key key}) : super(key: key);
#override
_MyNavigationBarState createState() => _MyNavigationBarState();
}
class _MyNavigationBarState extends State<MyNavigationBar>
with TickerProviderStateMixin {
int _selectedIndex = 0;
void changePage(int index) {
setState(() {
_selectedIndex = index;
});
}
Widget showPage(int selectedPage) {
if (selectedPage == 0) {
return Container(
child: Text('Main Page',
style: TextStyle(fontSize: 35, fontWeight: FontWeight.bold)),
);
} else if (selectedPage == 1) {
return Container(
child: Text('Category page',
style: TextStyle(fontSize: 35, fontWeight: FontWeight.bold)),
);
} else if (selectedPage == 2) {
return Container(
child: Text('Photo page',
style: TextStyle(fontSize: 35, fontWeight: FontWeight.bold)),
);
}
return Container(
child: Text('video Page',
style: TextStyle(fontSize: 35, fontWeight: FontWeight.bold)),
);
}
TabController tabController;
#override
void initState() {
// TODO: implement initState
super.initState();
tabController = TabController(initialIndex: 0, length: 2, vsync: this);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Container(
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.0),
//This is for bottom border that is needed
border:
Border(bottom: BorderSide(color: Colors.grey, width: 0.8))),
child: TabBar(
indicatorWeight: 2,
controller: tabController,
indicatorColor: Colors.purple,
labelColor: Colors.purple,
unselectedLabelColor: Color(0xff002540).withOpacity(0.7),
tabs: [
Tab(
child: Text(
"First",
),
),
Tab(
child: Text(
"Second",
),
),
],
),
),
backgroundColor: Colors.green,
),
body: SingleChildScrollView(
child: Column(
children: [
Container(
height: MediaQuery.of(context).size.height,
child: TabBarView(controller: tabController, children: [
Container(
child: Center(
child: showPage(_selectedIndex),
),
),
Container(
child: Center(
child: showPage(_selectedIndex),
),
),
]),
),
],
)),
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Main',
backgroundColor: Colors.blue),
BottomNavigationBarItem(
icon: Icon(Icons.category_outlined),
label: 'Category',
backgroundColor: Colors.blue),
BottomNavigationBarItem(
icon: Icon(Icons.book_online),
label: 'Photos',
backgroundColor: Colors.blue),
BottomNavigationBarItem(
icon: Icon(Icons.video_call),
label: 'Video',
backgroundColor: Colors.blue),
],
type: BottomNavigationBarType.shifting,
currentIndex: _selectedIndex,
selectedItemColor: Colors.black,
iconSize: 40,
onTap: changePage,
elevation: 5),
);
}
}
Output:

Flutter tab bar inside Appbar bottom give bottom overflow exception

I am using the below code. I got the bottom navigation bar to give an overflow exception. Please anyone help me to solve this problem.
return DefaultTabController(
length: 2,
child: Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
backgroundColor: Theme.of(context).primaryColor,
actions: [
IconButton(
onPressed: () {
openUrl("https://www.trustdidi.com/help");
},
icon: Icon(Icons.help_outline),
),
IconButton(
onPressed: () {
showComingSoonToast();
},
icon: Icon(Icons.notifications),
),
],
bottom: TabBar(
tabs: [
Tab(
icon: Icon(
Icons.directions_car,
color: Colors.white,
)),
Tab(icon: Icon(Icons.directions_transit)),
],
),
),
body: SafeArea(
child: TabBarView(
children: [
Icon(
Icons.directions_car,
color: Colors.redAccent,
),
Icon(Icons.directions_transit),
],
),
),
));
Buts it gives below error
you should try with tabbar controller.And then initial it
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
TabController _tabController;
#override
void initState() {
_tabController = new TabController(length: 2, vsync: this, initialIndex: 0);
super.initState();
}
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
backgroundColor: Theme.of(context).primaryColor,
actions: [
IconButton(
onPressed: () {
// openUrl("https://www.trustdidi.com/help");
},
icon: Icon(Icons.help_outline),
),
IconButton(
onPressed: () {
// showComingSoonToast();
},
icon: Icon(Icons.notifications),
),
],
bottom: TabBar(
controller: _tabController,
tabs: [
Tab(
icon: Icon(
Icons.directions_car,
color: Colors.white,
)),
Tab(icon: Icon(Icons.directions_transit)),
],
),
),
body: SafeArea(
child: TabBarView(
children: [
Icon(
Icons.directions_car,
color: Colors.redAccent,
),
Icon(Icons.directions_transit),
],
),
),
));
}
}
Output:

Flutter - Multi Page Navigation using bottom navigation bar icons

I'm trying to navigate to different pages within my app using the icons in my bottom navigation bar. I have tried many tutorials and can't seem to work out the best way to achieve this. I have created my Homepage (code below) and 2 additional pages, Inbox and Signin, both return simple scaffolds.
Firstly i'm interested to know if this is the best way to do what i'm trying to achieve and second, how can my code be altered to allow me to navigate to different pages depending on which icon is tapped. I'm aware that the code below doesn't execute, i'm just trying to show what i've tried.
My code:
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
_onTap(int index) {
Navigator.of(context)
.push(MaterialPageRoute<Null>(builder: (BuildContext context) {
return _children[_currentIndex];
}));}
final List<Widget> _children = [
HomePage(),
InboxPage(),
SignInPage()
];
int _currentIndex = 0;
#override
Widget build(BuildContext context) {
SizeConfig().init(context);
return Scaffold(
appBar: PreferredSize(preferredSize: Size(double.infinity, 75),
child: AppBar(
elevation: 0.0,
centerTitle: false,
title: Column(
children: <Widget>[
Align(
alignment: Alignment.centerLeft,
child: Text(
currentDate,
textAlign: TextAlign.left,
style: TextStyle(
color: titleTextColor,
fontWeight: subTitleFontWeight,
fontFamily: titleFontFamily,
fontSize: subTitleFontSize),
),
),
SizedBox(
height: 15,
),
Align(
alignment: Alignment.centerLeft,
child: Text(
'Some text here',
style: TextStyle(
color: titleTextColor,
fontWeight: titleTextFontWeight,
fontFamily: titleFontFamily,
fontSize: titleFontSize),
),
),
],
),
backgroundColor: kPrimaryColor,
shape: titleBarRounding
),
),
body: BodyOne(),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _currentIndex,
type: BottomNavigationBarType.fixed,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
title: Text('Home'),
),
BottomNavigationBarItem(
icon: Icon(Icons.mail),
title: Text('Inbox'),
),
BottomNavigationBarItem(
icon: Icon(Icons.account_circle),
title: Text('Account'),
)
],
onTap: () => _onTap(_currentIndex),
),);
}
}
Thanks in advance.
The screen you are in can't be part of the Screens you're navigating to and you don't need to push a new screen each time you just have to change selectedPage, this is an example of how it should look:
import 'package:flutter/material.dart';
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
int selectedPage = 0;
final _pageOptions = [
HomeScreen(),
InboxScreen(),
SignInScreen()
];
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: _pageOptions[selectedPage],
bottomNavigationBar: BottomNavigationBar(
items: [
BottomNavigationBarItem(icon: Icon(Icons.home, size: 30), title: Text('Home')),
BottomNavigationBarItem(icon: Icon(Icons.mail, size: 30), title: Text('Inbox')),
BottomNavigationBarItem(icon: Icon(Icons.account_circle, size: 30), title: Text('Account')),
],
selectedItemColor: Colors.green,
elevation: 5.0,
unselectedItemColor: Colors.green[900],
currentIndex: selectedPage,
backgroundColor: Colors.white,
onTap: (index){
setState(() {
selectedPage = index;
});
},
)
);
}
}
Let me know if you need more explanation.
The input parameter of the _onTap function is unused and needs to be deleted.
_onTap() {
Navigator.of(context)
.push(MaterialPageRoute(builder: (BuildContext context) => _children[_currentIndex])); // this has changed
}
In the onTap of the BottomNavigationBar you need to change the _currentIndex and then call the _onTap function which navigates to the selected screen.
onTap: (index) {
setState(() {
_currentIndex = index;
});
_onTap();
},
You can add this BottomNavigationBar to all of the screens, but pay attention to the initial value of the _currentIndex that changes according to the screen you're putting the BottomNavigationBar in.
Full code:
_onTap() { // this has changed
Navigator.of(context)
.push(MaterialPageRoute(builder: (BuildContext context) => _children[_currentIndex])); // this has changed
}
final List<Widget> _children = [
HomePage(),
InboxPage(),
SignInPage()
];
#override
Widget build(BuildContext context) {
SizeConfig().init(context);
return Scaffold(
appBar: PreferredSize(
preferredSize: Size(double.infinity, 75),
child: AppBar(
elevation: 0.0,
centerTitle: false,
title: Column(
children: <Widget>[
Align(
alignment: Alignment.centerLeft,
child: Text(
currentDate,
textAlign: TextAlign.left,
style: TextStyle(
color: titleTextColor,
fontWeight: subTitleFontWeight,
fontFamily: titleFontFamily,
fontSize: subTitleFontSize),
),
),
SizedBox(
height: 15,
),
Align(
alignment: Alignment.centerLeft,
child: Text(
'Some text here',
style: TextStyle(
color: titleTextColor,
fontWeight: titleTextFontWeight,
fontFamily: titleFontFamily,
fontSize: titleFontSize),
),
),
],
),
backgroundColor: kPrimaryColor,
shape: titleBarRounding
),
),
body: BodyOne(),
body: Container(),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _currentIndex,
type: BottomNavigationBarType.fixed,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
title: Text('Home'),
),
BottomNavigationBarItem(
icon: Icon(Icons.mail),
title: Text('Inbox'),
),
BottomNavigationBarItem(
icon: Icon(Icons.account_circle),
title: Text('Account'),
)
],
onTap: (index) { // this has changed
setState(() {
_currentIndex = index;
});
_onTap();
},
),
);
}
The best way to do it is creating a wrapper to your screens. Like this:
class Wrapper extends StatefulWidget {
Wrapper();
_WrapperState createState() => _WrapperState();
}
class _WrapperState extends State<Wrapper> {
int _currentIndex = 0;
final List<Widget> _children = [
HomePage(),
InboxPage(),
SignInPage()
];
void onTabTapped(int index) {
setState(() {
_currentIndex = index;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: _children[_currentIndex],
bottomNavigationBar: BottomNavigationBar(
onTap: onTabTapped,
currentIndex: _currentIndex,
items:[
BottomNavigationBarItem(
icon: Icon(Icons.home),
title: Text('Home'),
),
BottomNavigationBarItem(
icon: Icon(Icons.mail),
title: Text('Inbox'),
),
BottomNavigationBarItem(
icon: Icon(Icons.account_circle),
title: Text('Account'),
)
],
),
);
}
}

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.