BottomNavigationBarItem background color in flutter - flutter

i need to set background color to selected BottomNavigationBarItem like this image

It's not possible to change the background of a selected item of the BottomNavigationBar because that doesn't follow the design guidelines.
If you still want to use it that way, following the example given in BottomNavigationBar class, here is a workaround:
final _selectedItemColor = Colors.white;
final _unselectedItemColor = Colors.white30;
final _selectedBgColor = Colors.indigo;
final _unselectedBgColor = Colors.blue;
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;
});
}
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: kBottomNavigationBarHeight,
child: Material(
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(
appBar: AppBar(
title: const Text('BottomNavigationBar Sample'),
),
body: Center(
child: _widgetOptions.elementAt(_selectedIndex),
),
bottomNavigationBar: BottomNavigationBar(
selectedFontSize: 0,
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: _buildIcon(Icons.home, 'Home', 0),
title: SizedBox.shrink(),
),
BottomNavigationBarItem(
icon: _buildIcon(Icons.business, 'Business', 1),
title: SizedBox.shrink(),
),
BottomNavigationBarItem(
icon: _buildIcon(Icons.school, 'School', 2),
title: SizedBox.shrink(),
),
],
currentIndex: _selectedIndex,
selectedItemColor: _selectedItemColor,
unselectedItemColor: _unselectedItemColor,
),
);
}
Result:

As far as I can see, you cannot change the color of a tab when using BottomNavigationBar. However, can I suggest to switch to TabBar? It would look something like this:
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,
home: MyStatefulWidget(),
);
}
}
class MyStatefulWidget extends StatefulWidget {
MyStatefulWidget({Key key}) : super(key: key);
#override
_MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget>
with SingleTickerProviderStateMixin {
TabController _tabController;
#override
void initState() {
super.initState();
_tabController = TabController(vsync: this, length: 3);
}
#override
void dispose() {
_tabController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: TabBarView(
controller: _tabController,
children: <Widget>[
Scaffold(appBar: AppBar(title: Text('First'))),
Scaffold(appBar: AppBar(title: Text('Second'))),
Scaffold(appBar: AppBar(title: Text('Third'))),
],
),
bottomNavigationBar: BottomAppBar(
child: Container(
color: Colors.blue,
child: TabBar(
indicator: BoxDecoration(color: Colors.redAccent),
tabs: <Widget>[
Tab(child: Text("Stuff", style: TextStyle(color: Colors.white))),
Tab(child: Text("Things", style: TextStyle(color: Colors.white))),
Tab(child: Text("Items", style: TextStyle(color: Colors.white))),
],
controller: _tabController,
),
),
),
);
}
}
Result:
This is a very minimal example, but it demonstrates the gist of it.

Here is example for changing background on click:
class _MyWidgetState extends State<MyWidget> {
IconData selectedItem = Icons.dashboard;
List<IconData> get itemsList => _items.keys;
Map<IconData, String> _items = {
Icons.home: 'Home',
Icons.drive_eta: 'Delivery',
Icons.shopping_basket: 'Products',
Icons.mail: 'Messages'
};
#override
Widget build(BuildContext context) {
return BottomNavigationBar(
onTap: (int index) {
// todo something
setState(() {
selectedItem = itemsList[index];
});
},
currentIndex: itemsList.indexOf(selectedItem),
items: _items.entries.map((MapEntry<IconData, String> entry) {
return BottomNavigationBarItem(
icon: Icon(entry.key, color: Colors.white),
backgroundColor: entry.key == selectedItem ? Colors.black : Colors.blueGrey,
title: Text(entry.value),
);
}).toList());
}
}

Related

Flutter use Provider in BottomNavigationBar

I want to get data from Provider based on argument and populate that data into each BottomNavigationBarItem
On this screen I get "meetingId" argument and use that on Provider to populate a model class with data.
class MeetingDetailScreen extends StatefulWidget {
final meetingId;
const MeetingDetailScreen({Key? key, this.meetingId}) : super(key: key);
static const routeName = '/meeting-detail';
#override
_MeetingDetailScreenState createState() => _MeetingDetailScreenState();
}
class _MeetingDetailScreenState extends State<MeetingDetailScreen> {
String meetingId = '';
var _isInit = true;
var _isLoading = false;
final List<Widget> _pages = [
DetailsScreen(),
DocumentsScreen(),
AgendaScreen(),
MinutesScreen(),
];
int _selectedPageIndex = 0;
void _selectPage(int index) {
setState(() {
_selectedPageIndex = index;
});
}
#override
void initState() {
super.initState();
}
#override
void didChangeDependencies() {
if (_isInit) {
setState(() {
_isLoading = true;
});
//This is provider
Provider.of<MeetingDetails>(context)
.fetchAndSetMeetingDetails(widget.meetingId)
.then((_) {
setState(() {
_isLoading = false;
});
});
}
_isInit = false;
super.didChangeDependencies();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color.fromRGBO(242, 243, 248, 1),
appBar: AppBar(
backgroundColor: Colors.white,
centerTitle: true,
iconTheme: const IconThemeData(color: Color.fromRGBO(150, 188, 51, 1)),
title: Image.asset(
"assets/images/appbar-logo.png",
fit: BoxFit.contain,
height: 50,
),
),
drawer: const MainDrawer(),
body: _pages[_selectedPageIndex],
//body: getPage(_selectedPageIndex),
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.info_outline),
label: 'Details',
),
BottomNavigationBarItem(
icon: Icon(Icons.file_download),
label: 'Documents',
),
BottomNavigationBarItem(
icon: Icon(Icons.format_list_bulleted_outlined),
label: 'Agenda',
),
BottomNavigationBarItem(
icon: Icon(Icons.note_alt_outlined),
label: 'Minutes',
),
],
currentIndex: _selectedPageIndex,
selectedItemColor: Colors.amber[800],
onTap: _selectPage,
),
);
}
}
This is the BottomNavigationBarItem screen "DetailsScreen()"
class DetailsScreen extends StatelessWidget {
static const routeName = '/meeting-detail';
const DetailsScreen({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
final meetingDetailsList = Provider.of<MeetingDetails>(context);
final meetingDetails = meetingDetailsList.items.toList()[0];
return Center(
child: Text(
meetingDetails.event_name,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
);
}
}
Problem is Provider updates data from API and it takes a moment. when I try to use Provider data on BottomNavigationBar it throws an error because provider data is null when loading the screen. Is there any way to delay the BottomNavigationBarItem until Provider populates data?
Thank you
Problem is I wasn't using builder with ChangeNotifierProvider.
Inside widget I used following builder code and problem solved.
return Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ListView.builder(
shrinkWrap: true,
padding: const EdgeInsets.all(10.0),
itemCount: meeting.length,
itemBuilder: (ctx, i) => ChangeNotifierProvider.value(
value: meeting[i],
child:
buildDetailRow(context, 'Meeting Name', meeting[i].event_name),
),
),
],
);

Keep the bottomnavigationbar when Navigating to a new screen

I want to keep the bottomnavigationbar AppBar when navigating to a new screen. with save state when i back to page.
The trick is to use "IndexedStack" in the body, IndexedStack workers like Stack Widget :
IndexedStack(
index: _selectedIndex,
children: _widgetOptions,
)
pass list of widgets in 'children' & index of the widget in 'index'.
Here is the example code:
import 'package:flutter/material.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(
MyApp(),
);
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: BottomNavPage(),
);
}
}
class BottomNavPage extends StatefulWidget {
const BottomNavPage({Key? key}) : super(key: key);
#override
_BottomNavPageState createState() => _BottomNavPageState();
}
class _BottomNavPageState extends State<BottomNavPage> {
int _selectedIndex = 0;
static const List<Widget> _widgetOptions = <Widget>[
NavHome(),
Text('Index 1: Business'),
Text('Index 2: School'),
Text('Index 3: Settings'),
];
Widget navHome() {
return Text(
'Index 0: Home',
);
}
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('BottomNavigationBar Sample')),
body: IndexedStack(
index: _selectedIndex,
children: _widgetOptions,
),
bottomNavigationBar: Material(
child: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
backgroundColor: Colors.blue,
),
BottomNavigationBarItem(
icon: Icon(Icons.business),
label: 'Home',
backgroundColor: Colors.blue,
),
BottomNavigationBarItem(
icon: Icon(Icons.school),
label: 'Home',
backgroundColor: Colors.blue,
),
BottomNavigationBarItem(
icon: Icon(Icons.settings),
label: 'Home',
backgroundColor: Colors.blue,
),
],
currentIndex: _selectedIndex,
selectedItemColor: Colors.orange[400],
onTap: _onItemTapped,
),
),
);
}
}
class NavHome extends StatefulWidget {
const NavHome({
Key? key,
}) : super(key: key);
#override
_NavHomeState createState() => _NavHomeState();
}
class _NavHomeState extends State<NavHome> {
double _counter = 0;
void incrementCounter() {
setState(() {
_counter++;
});
}
void decrementCounter() {
setState(() {
_counter--;
});
}
#override
Widget build(BuildContext context) {
// Return a widget number in the center of the screen and button to increment the number
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Counter',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
child: Text('Increment'),
onPressed: incrementCounter,
),
SizedBox(width: 10),
ElevatedButton(
child: Text('Decrement'),
onPressed: decrementCounter,
),
],
),
],
),
);
}
}

How to Load Data in a particular Tab in Bottom Nav Bar in Flutter

I am using an Animated Container in Bottom Nav Bar to Hide the Bottom Navbar While Scrolling(Similar to Pinterest). I want to display The data of particular tab in the Same Page. (refer the GIF)
https://i.stack.imgur.com/xlOsy.gif
I Want to display the Content In the Screen of the tab and I don't want to route to other Screen leaving the main Screen. I have 4 rows with different Icons. How Can I achieve this?
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
double yTransValue = 0;
#override
Widget build(BuildContext context) {
return NotificationListener<ScrollUpdateNotification>(
onNotification: (notification) {
print(notification.metrics.axisDirection);
print(notification.metrics.axis);
if (notification.scrollDelta.sign == 1) {
setState(() {
yTransValue = 100;
});
} else if (notification.scrollDelta.sign == -1) {
setState(() {
yTransValue = 0;
});
}
},
child: Scaffold(
body: ListView.builder(
itemBuilder: (BuildContext context, int index) {
return SizedBox(
height: 260,
child: Card(
child: Center(child: Text('Item #$index')),
),
);
},
),
bottomNavigationBar: AnimatedContainer(
duration: Duration(milliseconds: 300),
transform: Matrix4.translationValues(0, yTransValue, 0),
child: SizedBox(
height: 60,
child: Card(
color: Colors.grey,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Icon(Icons.home),
Icon(Icons.search),
Icon(Icons.favorite_border),
Icon(Icons.person_rounded),
],
),
),
),
),
),
);
}
}
I had tried Wrapping the Icons With 'Gesture Detector' But when the Icon is pressed a data is loaded in new Screen.
Use the following code:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
/// This 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(),
);
}
}
/// This is the stateful widget that the main application instantiates.
class MyStatefulWidget extends StatefulWidget {
MyStatefulWidget({Key key}) : super(key: key);
#override
_MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}
/// This is the private State class that goes with MyStatefulWidget.
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: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.business),
label: 'Business',
),
BottomNavigationBarItem(
icon: Icon(Icons.school),
label: 'School',
),
],
currentIndex: _selectedIndex,
selectedItemColor: Colors.amber[800],
onTap: _onItemTapped,
),
);
}
}

How to style BottomNavigationBarItem label

In my application I have a BottomNavigationBar.
I am implementing multi navigation with bottom navigation bar as shown here;
https://medium.com/coding-with-flutter/flutter-case-study-multiple-navigators-with-bottomnavigationbar-90eb6caa6dbf
I have put the title text like this.
BottomNavigationBarItem _buildItem(
{TabItem tabItem, String tabText, IconData iconData}) {
return BottomNavigationBarItem(
icon: Icon(
iconData,
color: widget.currentTab == tabItem
? active_button_color
: Colors.grey,
),
//label: tabText,
title: Text(
tabText,
style: widget.currentTab == tabItem
? Archivo_12_0xff002245
: Archivo_12_grey,
),
);
I get message title is deprecated.
When I use the label parameter how do I style it?
You style it using properties on the BottomNavigationBar.
Example:
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'First',
),
BottomNavigationBarItem(
icon: Icon(Icons.exit_to_app),
label: 'Second',
),
],
selectedLabelStyle: TextStyle(fontSize: 22),
selectedItemColor: Colors.red,
),
There are of course more properties. Check the documentation on: https://api.flutter.dev/flutter/material/BottomNavigationBar-class.html
As the message already indicates that the 'title' property is deprecated, it has been replace with 'label'.
Concerning the selected color not changing, you need to add a function call 'onItemTapped' to change the color by setting the state.
The following is the working code:
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key key}) : super(key: key);
static const String _title = 'TEST';
#override
Widget build(BuildContext context) {
return const MaterialApp(
title: _title,
home: MyStatefulWidget(),
);
}
}
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({Key key}) : super(key: key);
#override
_MyStatefulWidgetState 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: First',
style: optionStyle,
),
Text(
'Index 1: Second',
style: optionStyle,
),
];
//METHOD TO SET STATE
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('BottomNavigationBar'),
),
body: Center(
child: _widgetOptions.elementAt(_selectedIndex),
),
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'First',
),
BottomNavigationBarItem(
icon: Icon(Icons.exit_to_app),
label: 'Second',
),
],
selectedLabelStyle: TextStyle(fontSize: 22),
selectedItemColor: Colors.red,
//THIS METHOD NEEDS TO BE CALLED TO CHANGE THE STATE
onTap: _onItemTapped,
currentIndex: _selectedIndex),
);
}
}
There is a bit differences and changes in new flutter for BottomNavigationBar for example title has been changed to label , style in that title moved from BottomNavigationBarItem to BottomNavigationBar as selectedLabelStyle and unselectedLabelStyle etc. So the new solution will something like below:
#override
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: BottomNavigationBar(
currentIndex: currentTab,
onTap: (index) => setState(() => currentTab = index),
type: BottomNavigationBarType.fixed,
selectedLabelStyle: Archivo_12_0xff002245,
unselectedLabelStyle: Archivo_12_grey,
items: [
_buildItem(),
],
),
);
}
BottomNavigationBarItem _buildItem(
{TabItem tabItem, String tabText, IconData iconData}) {
return BottomNavigationBarItem(
icon: Icon(
iconData,
color: widget.currentTab == tabItem ? active_button_color : Colors.grey,
),
label: tabText,
);
}

Change AppBar title depending on page with BottomNavigationBar

I'm trying to change the AppBar title depending on which page the user is on - the pages are controlled by a BottomNavigationBar which loads the different classes(pages)
The only way i've managed to change this is by including a appbar for each page, which i believe is not the way to go ahead.
class HomePage extends StatefulWidget {
final String title;
HomePage({Key key, this.auth, this.userId, this.onSignedOut, this.title})
: super(key: key);
final BaseAuth auth;
final VoidCallback onSignedOut;
final String userId;
#override
State<StatefulWidget> createState() => new _HomePageState();
}
class _HomePageState extends State<HomePage> {
int _currentIndex = 0;
final List<Widget> _children = [
Projects(),
TimedProject(),
Overview(),
Clients(),
];
GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey();
#override
Widget build(BuildContext context) {
return new Scaffold(
key: _scaffoldKey,
appBar: AppBar(
title: Text('TITLE I NEED TO CHANGE DEPENDING ON PAGE',
style: TextStyle(color: Colors.black),
),
backgroundColor: Colors.white,
),
endDrawer: AppDrawer(),
body: _children[_currentIndex],
bottomNavigationBar: BottomNavigationBar(
onTap: onTabTapped,
currentIndex: _currentIndex,
selectedItemColor: Theme.of(context).primaryColor,
type: BottomNavigationBarType.fixed,
items: [
new BottomNavigationBarItem(
icon: Icon(Icons.storage),
title: Text('Jobs'),
),
new BottomNavigationBarItem(
icon: Icon(Icons.timer),
title: Text('Timer'),
),
new BottomNavigationBarItem(
icon: Icon(Icons.pie_chart_outlined),
title: Text('Overview'),
),
new BottomNavigationBarItem(
icon: Icon(Icons.supervisor_account), title: Text('Clients'))
],
),
);
}
void onTabTapped(int index) {
setState(() {
_currentIndex = index;
});
}
}
Create a variable that holds the appbar title or you can use the same title variable that is passed in your HomePage class but you have to remove the final.
If you are using the title variable in HomePage class, make sure to use
"widget.title"
class HomePage extends StatefulWidget {
final String title;
HomePage({Key key, this.auth, this.userId, this.onSignedOut, this.title})
: super(key: key);
final BaseAuth auth;
final VoidCallback onSignedOut;
final String userId;
#override
State<StatefulWidget> createState() => new _HomePageState();
}
class _HomePageState extends State<HomePage> {
int _currentIndex = 0;
String _title;
final List<Widget> _children = [
Projects(),
TimedProject(),
Overview(),
Clients(),
];
GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey();
#override
initState(){
_title = 'Some default value';
}
#override
Widget build(BuildContext context) {
return new Scaffold(
key: _scaffoldKey,
appBar: AppBar(
title: Text(_title,
style: TextStyle(color: Colors.black),
),
backgroundColor: Colors.white,
),
endDrawer: AppDrawer(),
body: _children[_currentIndex],
bottomNavigationBar: BottomNavigationBar(
onTap: onTabTapped,
currentIndex: _currentIndex,
selectedItemColor: Theme.of(context).primaryColor,
type: BottomNavigationBarType.fixed,
items: [
new BottomNavigationBarItem(
icon: Icon(Icons.storage),
title: Text('Jobs'),
),
new BottomNavigationBarItem(
icon: Icon(Icons.timer),
title: Text('Timer'),
),
new BottomNavigationBarItem(
icon: Icon(Icons.pie_chart_outlined),
title: Text('Overview'),
),
new BottomNavigationBarItem(
icon: Icon(Icons.supervisor_account), title: Text('Clients'))
],
),
);
}
void onTabTapped(int index) {
setState(() {
_currentIndex = index;
switch(index) {
case 0: { _title = 'Jobs'; }
break;
case 1: { _title = 'Timer'; }
break;
case 2: { _title = 'Overview'; }
break;
case 3: { _title = 'Clients'; }
break;
}
});
}
}
Thanks for the solution, is there away to take the bottom nav and out it in its own .dart file like
bottomNavigationBar: BottomNavBar(),
and get the selected tab index
class _HomeScreen2State extends State<HomeScreen2> {
//Hold current Tab Index
int _selectTab = 0;
final _pageOptions = [
HomeScreen(),
NewOrderScreen(),
OrderHistoryScreen(),
ContactScreen(),
];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Gift Shop Dashboard'),
),
body: _pageOptions[_selectTab],
bottomNavigationBar: BottomNavBar(),
);
}
}
To separate BottomNavigationBar in a different .dart file, for example, in config.dart:
import 'package:flutter/material.dart';
class Config {
static List<BottomNavigationBarItem> navigationBarItems = [
BottomNavigationBarItem(
icon: Icon(
Icons.date_range,
),
title: Text(
"Calendar",
),
),
BottomNavigationBarItem(
icon: Icon(
Icons.list, // event_note
),
title: Text(
"List",
),
),
BottomNavigationBarItem(
icon: Icon(
Icons.bookmark_border, // grid_on
),
title: Text(
"Bookmarks",
),
),
BottomNavigationBarItem(
icon: Icon(
Icons.account_circle,
),
title: Text(
"Me",
),
),
];
static BottomNavigationBar navigationBar = BottomNavigationBar(
items: navigationBarItems,
type: BottomNavigationBarType.fixed,
fixedColor: Colors.red,
);
}
and in main.dart:
import 'package:flutter/material.dart';
import 'config.dart';
void main() => runApp(App());
class App extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Hello',
theme: ThemeData(
primarySwatch: Colors.blueGrey,
),
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
HomePage({Key key}) : super(key: key);
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
int _index = 0;
Text _title;
_onTap(int index) {
setState(() {
_index = index;
_title = Config.navigationBarItems[_index].title;
});
}
#override
void initState() {
_title = Config.navigationBarItems[_index].title;
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: _title,
),
body: Container(
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _index,
type: Config.navigationBar.type,
fixedColor: Config.navigationBar.fixedColor,
items: Config.navigationBar.items,
onTap: _onTap,
),
);
}
}
just make condition in ontap
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
int _selectedIndex = 1;
String appbarTitleString = "Home";
var appBarTitleText = new Text("Home");
static const TextStyle optionStyle =
TextStyle(fontSize: 30, fontWeight: FontWeight.bold);
static const List<Widget> _widgetOptions = <Widget>[
Text(
'Index 0: Profile',
style: optionStyle,
),
Text(
'Index 1: Home',
style: optionStyle,
),
Text(
'Index 2: More',
style: optionStyle,
),
];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: appBarTitleText,
),
body: Center(
child: _widgetOptions.elementAt(_selectedIndex),
),
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.business),
title: Text('Profile'),
),
BottomNavigationBarItem(
icon: Icon(Icons.home),
title: Text('Home'),
),
BottomNavigationBarItem(
icon: Icon(Icons.school),
title: Text('More'),
),
],
currentIndex: _selectedIndex,
selectedItemColor: Colors.amber[800],
onTap: _onItemTapped,
),
);
}
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
if (index == 0){
appbarTitleString = "Profile" ;
appBarTitleText = new Text(appbarTitleString);
}else if (index == 1){
appbarTitleString = "Home" ;
appBarTitleText = new Text(appbarTitleString);
}else if(index == 2){
appbarTitleString = "More" ;
appBarTitleText = new Text(appbarTitleString);
}
});
}
}
it is too Simple, using only two variable we can handle it.
Take Two Variables like:
int _selectedIndex = 0;
String _page_title = "DashBoard";
and Replace page title on every index changed. like as below,
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
if (index == 0) {
_page_title = "DashBoard";
} else if (index == 1) {
_page_title = "Search";
} else if (index == 2) {
_page_title = "Setting";
} else if (index == 3) {
_page_title = "Profile";
}
});
make a list which decide to perform task from selected tab.
static const List<Widget> _widgetOptions = <Widget>[
Text(
'Home 1',
style: optionStyle,
),
Text(
'Home 2',
style: optionStyle,
),
Text(
'Home 3',
style: optionStyle,
),
Profile(),
];
And adjust code in Build() function as below.
#override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text(_page_title),
automaticallyImplyLeading: false, // hide back arrow from appbar
),
body: Center(
child: _widgetOptions.elementAt(_selectedIndex),
),
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(
Icons.home,
color: Colors.grey,
),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(
Icons.search,
color: Colors.grey,
),
label: 'Search',
),
BottomNavigationBarItem(
icon: Icon(
Icons.settings,
color: Colors.grey,
),
label: 'Setting',
),
BottomNavigationBarItem(
icon: Icon(
Icons.face_retouching_natural_sharp,
color: Colors.grey,
),
label: 'Profile',
),
],
currentIndex: _selectedIndex,
selectedItemColor: Colors.blue,
onTap: _onItemTapped,
),
);
}
}
☻♥ Done.
In case you also have different actions, leadings, etc for different pages, You can have different appbars in separate files and import them like pages.
static final List<Widget> _pages = [
const HomeScreen(),
const BookingScreen(),
const AccountScreen(),
];
static final List<Widget> _appBars = [
const HomeAppBar(),
const BookingAppBar(),
const AccountAppBar(),
];
Then you can have variable:
int _selectedIndex = 0;
Your onTapped function will be like:
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
Your build would be like this:
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: PreferredSize(
preferredSize: const Size.fromHeight(56), // 56 is default height
child: _appBars[_selectedIndex],
), // PreferredSize
body: _pages[_selectedIndex],
bottomNavigationBar: BottomNavigationBar(
currentIndex: _selectedIndex,
onTap: _onItemTapped,
items: const [
BottomNavigationBarItem(
icon: Icon(Icons.home_rounded),
label: "Home",
), // BottomNavigationBarItem
BottomNavigationBarItem(
icon: Icon(Icons.schedule_rounded),
label: "Bookings",
), // BottomNavigationBarItem
BottomNavigationBarItem(
icon: Icon(Icons.person_rounded),
label: "Account",
), // BottomNavigationBarItem
],
), // BottomNavigationBar
); // Scaffold
}