BottomNavigationBar // Cannot control item label color - flutter

Goal: I want to give the item label a specific font and color depending on if it is selected or not.
My approach: As the label cannot be styled directly, I'm using the properties "unselectedLabelStyle" and "selectedLabelStyle".
The Problem:
The properties work for font and fontweight, but I cannot directly control the text color
I can influence the label color of the selected item; but not with the "selectedLabelStyle" property, but with the color I specifiy under "seltectedItemColor".
"unselectedLabelStyle" also works for font and fontweight, but not for the color. I cannot find a property, that would allow me to change the color. > THIS IS THE PROBLEM
Pretty picture (code below):
The code:
BottomNavigationBar(
elevation: 0,
onTap: (index) => selectPage(index),
currentIndex: selectedPageIndex,
selectedItemColor:
Provider.of<CustomColors>(context).customColorScheme['Dark Teal'],
unselectedLabelStyle:
Provider.of<CustomTextStyle>(context, listen: false)
.customTextStyle('IconLabel'),
selectedLabelStyle:
Provider.of<CustomTextStyle>(context, listen: false)
.customTextStyle('IconLabel'),
backgroundColor: Colors.white,
type: BottomNavigationBarType.fixed,
items: [
//home
bottomNavIcon(
context: context,
icon: Image.asset(
"assets/icons/icon_home.png",
),
icon_active: Image.asset("assets/icons/icon_home.png",
color: Provider.of<CustomColors>(context)
.customColorScheme['Dark Teal']),
label: 'Home',
),
//favorite
bottomNavIcon(
context: context,
icon: Image.asset("assets/icons/icon_favorite.png"),
icon_active: Image.asset("assets/icons/icon_favorite.png",
color: Provider.of<CustomColors>(context)
.customColorScheme['Dark Teal']),
label: 'Favorite',
),
//loockback
bottomNavIcon(
context: context,
icon: Image.asset("assets/icons/icon_lookback.png"),
icon_active: Image.asset("assets/icons/icon_lookback.png",
color: Provider.of<CustomColors>(context)
.customColorScheme['Dark Teal']),
label: 'Lookback',
),
//info & support
bottomNavIcon(
context: context,
icon: Image.asset("assets/icons/icon_info.png"),
icon_active: Image.asset("assets/icons/icon_info.png",
color: Provider.of<CustomColors>(context)
.customColorScheme['Dark Teal']),
label: 'Info & Support',
),
],
),
Code for the icons
BottomNavigationBarItem bottomNavIcon(
{required BuildContext context,
required Image icon,
required Image icon_active,
required String label}) {
return BottomNavigationBarItem(
icon: Padding(
padding: EdgeInsets.only(top: 6.h, bottom: 3.h),
child: icon,
),
activeIcon: Padding(
padding: EdgeInsets.only(top: 6.h, bottom: 3.h),
child: icon_active,
),
label: label,
);
}

If you want the unselected items to have a certain color, use:
unselectedItemColor: Colors.red,
This will change the color of label and icon both for unselected items.
Example:
Unfortunately, unselectedLabelStyle property works for changing font weight, font size etc but not for color.
Also check this answer for unselectedLabelstyle don't work in Flutter

As the docmumentation say's, you can change the text color using the color property of TextStyle : https://api.flutter.dev/flutter/painting/TextStyle-class.html
Once this say's perharps BottomNavigationBar overide the color when setting selectedItemColor and/or unselectedItemColor
After giving a try, effectively color is overide even if you don't provide selectedItemColor and/or unselectedItemColor

Related

Flutter how to remove open routes when changing page inside IndexedStack

In my app I have a NavigationRail on the left and the main body on the right. I'm using nested Navigators so that when a widget inside the IndexedStack pushes a new route the NavigationRail stays on the screen. But this generates a problem when there is a new Navigator Route on the screen and I try to change the page with NavigationRail it changes the selected icon, but the Navigator route stays on the screen.
Row(
children: [
// GestureDetector uses onHorizontalDragStart to make the Navigation
// Rail extend or shrink
GestureDetector(
onHorizontalDragStart: (details) {
setState(() {
_navRailExtended = !_navRailExtended;
});
},
child: NavigationRail(
// The width of the navigation rail
minExtendedWidth: 180,
// Text and icon themes for selected destinations
selectedIconTheme:
IconThemeData(color: Colors.purple[600]),
selectedLabelTextStyle: TextStyle(
color: Colors.purple[600],
fontWeight: FontWeight.bold,
fontSize: 16),
// Text and icon themes for unselected destinations
unselectedIconTheme:
IconThemeData(color: Colors.grey[200]),
unselectedLabelTextStyle: TextStyle(
color: Colors.grey[400],
fontWeight: FontWeight.bold,
fontSize: 15),
// Background color of the navigation rail, typical
// color for the dark theme in Flutter
backgroundColor: const Color.fromARGB(255, 47, 47, 47),
// extended makes the navigation rail wider
extended: _navRailExtended,
selectedIndex: _pageIndex,
onDestinationSelected: (int index) {
setState(() {
_pageIndex = index;
});
},
destinations: const <NavigationRailDestination>[
NavigationRailDestination(
icon: Icon(Icons.explore_rounded, size: 35),
label: Text('Discover'),
),
NavigationRailDestination(
icon: Icon(Icons.home_filled, size: 35),
label: Text('Notebook'),
),
NavigationRailDestination(
icon: Icon(Icons.games_sharp, size: 35),
label: Text('Games'),
),
NavigationRailDestination(
icon: Icon(Icons.analytics_outlined, size: 35),
label: Text('Analytics'),
),
],
),
),
// A vertical divider between the navigation rail and the body
const VerticalDivider(thickness: 1.5, width: 1),
// Expanded makes the body of the windows app centered
// (without it the row widget would screw up the sizing of the app)
Expanded(
// Navigator makes all new routes inside the main pages
// opened with 'Navigator.pop()' ignore the navigation rail,
// i.e. the navigation rail will always stay opened
child: Navigator(
onGenerateRoute: (settings) {
return MaterialPageRoute(builder: ((context) {
// Indexed Stack keeps the state of each page unchanged
return IndexedStack(
index: _pageIndex,
children: const [Discover(), NoteBook(), Games(), Analytics()],
);
}));
},
),
)
],
)
App on the start:
When there is a new Navigator route on the screen:
I try to change the page:
What it should do:

Hide Elevation Button shadow when I tapping on it

How can I hide ElevatedButton shadow, when I tapping on it. Or maybe I can use some differnt button, I need property to change shadow color and elevation. I tried to use ElevationButton(but it doesn't hide shadow when I tapped on it, on the contrary shadow becaming bigger). I alse tried to use RaisedButton, but it doesn't have property for changing shadow color.
ElevatedButton(
onPressed: (){},
style: ElevatedButton.styleFrom(
shadowColor: Colors.transparent,
),
child: Container(),
),
You can also use RawMaterialButton
Found solution, you just need to oveeride elevation in ButtonStyle with MaterialStateProperty, and set other parametrs as you need.
ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all<Color>(activeColor),
overlayColor: MaterialStateProperty.all<Color>(pressedColor),
shadowColor: MaterialStateProperty.all<Color>(shadowColor),
padding:
MaterialStateProperty.all<EdgeInsetsGeometry>(EdgeInsets.zero),
shape: MaterialStateProperty.all<OutlinedBorder>(border),
elevation: MaterialStateProperty.resolveWith<double>(
(Set<MaterialState> states) {
if (states.contains(MaterialState.pressed)) {
return 0;
}
if (states.contains(MaterialState.focused)) {
return elevation;
}
if (states.contains(MaterialState.hovered)) {
return elevation;
}
return elevation;
}),
),
onPressed: onPressed,
child: textBody,
),

Flutter - Disable Bottom Navigation Bar Animation (growing text)

I want to disable the Bottom Navigation Bar animation for selected item to get the same text/icon size of unselected items.
That's my code:
class BottomNavigationBarHome extends StatelessWidget {
#override
Widget build(BuildContext context) {
return BottomNavigationBar(
unselectedItemColor: Colors.black38,
backgroundColor: Colors.white,
items: [
BottomNavigationBarItem(
icon: Icon(BalanceIcon.scale_balance, size: 15.0),
title: Text('Item 1', style: TextStyle(
),)
),
BottomNavigationBarItem(
icon: Icon(BalanceIcon.scale_balance),
title: Text('Item 2')
),
BottomNavigationBarItem(
icon: Icon(BalanceIcon.scale_balance),
title: Text('Item 3')
),
]
);
}
}
I have already tried setting the same font size, the animation is still here
You can try add type to BottomNavigationBar
BottomNavigationBar(
type: BottomNavigationBarType.fixed,
...
)
The previous answers are correct but you need a combination of both, fixed type and defined font sizes:
BottomNavigationBar(
type: BottomNavigationBarType.fixed,
selectedFontSize: 12.0,
unselectedFontSize: 12.0,
...
)
BottomNavigationBarType.fixed prevents the items from moving horizontally and makes the labels of the unselected items visible.
selectedFontSize: 12.0, unselectedFontSize: 12.0 prevents the font size change when selecting an item that happens even if the type is fixed.
To re-add the gap between icon and label that disappears with this configuration, you can add a bottom padding to the icons in your BottomNavigationBarItem:
BottomNavigationBarItem(
icon: Padding(
padding: EdgeInsets.only(bottom: 2.5),
child: <your icon>,
),
label: <your title>,
),
Add selectedFontSize & unselectedFontSize in BottomNavigationBar and set the same font sizes
BottomNavigationBar(
selectedFontSize: 15.0,
unselectedFontSize: 15.0,

Title Only On Selected Bottom Navigation Bar

I am trying to create an effect on the Bottom Navigation Bar such as that of Google Drive. I want the title of the item only to be displayed, on the selected item, and the others to only display the icons.
Also, this bottom bar becomes somewhat transparent, so you can barely see what's under it. Is this possible to do in flutter? I know it is not possible on the main app bar, since there is an issue talking about it here
image for reference
Hide Title of Unselected BottomNavigationBarItem
You just need to set the show unselected labels property of the bottom navigation bar to false
showUnselectedLabels: false,
Transparent BottomNavigation bar
The Scaffold provides placeholders for both Appbar and BottomNavigation bars. This is how they are placed.
The problem here is that the body does not overlap the Appbar or the BottomNavigation bar, and thus even if you give transparent background it would appear to do nothing.
A workaround would be to put the Body, AppBar and BottomNavigationBar inside a stack and position the AppBar and BottomNavigationBar appropriately.
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: <Widget>[
Container(
color: Colors.green, // Content of body here
),
Positioned(
left: 0,
right: 0,
top: 0,
child: AppBar(
elevation: 0,
backgroundColor: Colors.indigo.withAlpha(80),
title: Text('Some Text'),
),
),
Positioned(
left: 0,
right: 0,
bottom: 0,
child: BottomNavigationBar(
elevation: 0,
showUnselectedLabels: false,
backgroundColor: Colors.red.withAlpha(80),
items: [
BottomNavigationBarItem(
title: Text('A'),
icon: Icon(Icons.add),
),
BottomNavigationBarItem(
title: Text('B'),
icon: Icon(Icons.remove),
),
],
),
),
],
),
);
}
}
U should use this code :
bottomNavigationBar: BottomNavigationBar(
//use both properties
type: BottomNavigationBarType.fixed,
showUnselectedLabels: true,
//-----------
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.icon1),
label:'item 1',
),
BottomNavigationBarItem(
icon: Icon(Icons.icon2),
label: 'item 2',
),
],
)

Custom style or theme for Expansion Tile Header, Flutter

Is there any way to apply custom theme for ExpansionTile. In my case, I want to have the different background colour for Header and children of the expansion tile but When ever the ExpansionTile is expanded, Headers background color changes to that of children?
To apply a custom Theme to any widget, just wrap it with the Theme() widget.
and then specify your custom theme in the data field of the widget.
Theme(
data: ThemeData(/*specify your custom theme here*/),
child: ExpansionTile() /*or any other widget you want to apply the theme to.*/
)
In your case, to customise the header in ExpansionTile,
when ExpansionTile is closed
the style of header text i.e. title depends on
ThemeData.textTheme.subhead (in flutter 2 it's ThemeData.textTheme.subtitle1)
whereas, the style of the arrow icon depends
on ThemeData.unselectedWidget (in flutter 2 it's ThemeData.unselectedWidgetColor)
when ExpansionTile is open
the color of both the widgets depends on ThemeData.accentColor
In a similar fashion you can customise almost any part of the expansion tile by tweaking the theme. For more details check out this link.
Since flutter is built with flexibility in mind. You can do almost anything you want. Create almost any UI you want.
Following the idea of #user3315892, you can implement your own stateful widget for the ExpansionTile, so that you can control what colours you want the header and children to be when the header is expanded or collapsed.
The following example only changes the text foreground and background colours of the header when the expansion tile is expanded or collapsed, but you can do the same for the children widgets.
class CustomExpansionTile extends StatefulWidget {
#override
State createState() => CustomExpansionTileState();
}
class CustomExpansionTileState extends State<CustomExpansionTile> {
bool isExpanded = false;
#override
Widget build(BuildContext context) {
return ExpansionTile(
title: Container(
child: Text(
"HEADER HERE",
style: TextStyle(
color: isExpanded ? Colors.pink : Colors.teal,
),
),
// Change header (which is a Container widget in this case) background colour here.
color: isExpanded ? Colors.orange : Colors.green,
),
leading: Icon(
Icons.face,
size: 36.0,
),
children: <Widget>[
Text("Child Widget One"),
Text("Child Widget Two"),
],
onExpansionChanged: (bool expanding) => setState(() => this.isExpanded = expanding),
);
}
}
I found another way to do it. I don't know if this is the best way but it's simpler for me.
To change the ExpansionTile color, you can wrap it with a Container and give it a color. This will change the entire color of the ExpansionTile, both collapsed and expanded.
But if you want a different color for the children, you can also wrap them with a Container and set another color there. However, keep in mind that you have to "expand" that Container to occupy all the available space (you can do it by setting width and height parameters properly).
Btw, that doesn't change the arrow color.
Widget expansionTileTest(context) {
return Container(
color: Colors.grey,
child: ExpansionTile(
title: Text(
"Title",
style: TextStyle(color: Colors.black),
),
children: <Widget>[
Container(
height: MediaQuery.of(context).size.height * 0.1,
width: MediaQuery.of(context).size.width,
color: Colors.yellow,
child: Center(child: Text("Hi")),
),
],
),
);
}
Collapsed
Expanded
You can set color of header and then body/children wrap in Container and set color to that container.
I used this code to make the trailing ion color Black.
Theme(
data: Theme.of(context).copyWith(accentColor: Colors.black),
child: ExpansionTile(
backgroundColor: Colors.white,
title: Text(
'Title Exmample',
style: TextStyle(color: Colors.black),
),
leading: CircleAvatar(
backgroundColor: Colors.black.withOpacity(.07),
child: Icon(
Icons.apps_outlined,
color: Theme.of(context).primaryColor,
)),
children: _buildTiles(Theme.of(context).primaryColor, Colors.black.withOpacity(.07), context),
),
);
If you want the ExpansionTile title to remain the same color whether closed or expanded, you can set it's style:
ExpansionTile(
title: Text('HEADER HERE', style: TextStyle(color: Colors.red)),
...
),
Additional styling for ExpansionTile is an open feature request:
Feature request: More styling of ExpansionTile #15427