'How do I set AppBar action button color in Flutter
I'm trying to set the color of my AppBar
action icons by using themes but it's just not working for some reason. Here's my minimal code example:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
iconTheme: IconThemeData(color: Colors.purple),
primaryIconTheme: IconThemeData(color: Colors.red),
accentIconTheme: IconThemeData(color: Colors.amber)
),
home: Scaffold(
appBar: AppBar(
iconTheme: IconThemeData(color: Colors.green),
actionsIconTheme: IconThemeData(color: Colors.yellow),
actions: [
IconButton(icon: Icon(Icons.add))
]
)
));
}
}
- None of the
iconTheme
color values have any effect. - Settings the opacity in either the
MaterialApp.iconTheme
,AppBar.iconTheme
orAppBar.actionsIconTheme
does actually take effect - Explicitly setting
Icon.color
does work but I don't think I should have to do that right?
How do I get the IconButton
to respect my theme?
Thanks Thomas
EDIT: By using a Icon
directly instead of an IconButton
I'm actually able to get the icon to respect my theme, but how do I make that clickable? According to https://api.flutter.dev/flutter/material/AppBar/actions.html an IconButton
is the most common widget to use in AppBar.actions
. Is that incorrect?
Solution 1:[1]
So, apparently my problem was that I hadn't defined the onPressed
property of the IconButton
. Once I added that, my theme was applied properly.
I knew it was a required property but I didn't get any error when building/running the app.
Solution 2:[2]
Make class of common for App Bar Widget
enum ButtontType {
back,
menu
}
class topBarWidget {
//region TopBar
static AppBar createTopBar(
{
String title,
double elevation = 1.5,
TextStyle titleStyle,
Widget titleWidget,
List<ButtontType> leftIcons = const [],
List<ButtontType> rightIcons = const [],
ButtonTapCallback action,
EdgeInsetsDirectional padding = const EdgeInsetsDirectional.only(start: 10, end: 10.0),
Color backgroundColor,
Color iconColor,
bool centerTitle = true}) {
var titleText = titleWidget;
if (titleText == null) {
titleText = Text(
title,
softWrap: true,
style: txtStyle,
),
);
}
var leftmenuWidget;
List<Widget> rightRowChildern = [];
final size = 18.0;
final tapAreasize = 32.0;
if (leftIcons.length > 0) {
List<Widget> mainRowChildern = [];
mainRowChildern.add(Padding(padding: EdgeInsets.only(left: 10.0)));
for (int i = 0; i < leftIcons.length; i++) {
final menuIconImage = Image.asset(_getImageName(type: leftIcons[i]),color: Colors.black,);
final menuIconImageSizeBox = SizedBox(child: menuIconImage, width: size, height: size,);
// ignore: unnecessary_statements
final menuIconAction = Container(color: Colors.transparent,child: InkWell(onTap: () {(action != null) ? action(leftIcons[i]) : null;},child: ClipOval(child: Container(alignment: Alignment.center,width: tapAreasize,height: tapAreasize,color: Colors.transparent,child:menuIconImageSizeBox,),),),);
//final menuIconAction = InkWell(child: menuIconImageSizeBox, onTap: () => (action != null) ? action(leftIcons[i]) : null, );
mainRowChildern.add(menuIconAction);
}
leftmenuWidget = Row(children: mainRowChildern, mainAxisAlignment: MainAxisAlignment.start,);
}
if (rightIcons.length > 0) {
for (int i = 0; i < rightIcons.length; i++) {
Widget menuIconImage = Image.asset(_getImageName(type: rightIcons[i]),color: Colors.black,);
if(_getImageName(type: rightIcons[i]) == _getImageName(type: ButtontType.notificationUnread)){
menuIconImage = Image.asset(_getImageName(type: rightIcons[i]),);
} else{
menuIconImage = Image.asset(_getImageName(type: rightIcons[i]),color: Colors.yellow,);
}
var menuIconImageSizeBox;
menuIconImageSizeBox = SizedBox(child: menuIconImage, width: size * 1.5, height: size * 1.5,);
final menuIconAction = InkWell(child: menuIconImageSizeBox, onTap: () => (action != null) ? action(rightIcons[i]) : null,);
rightRowChildern.add(menuIconAction);
if (i != (rightIcons.length - 1)) {
rightRowChildern.add(Padding(padding: EdgeInsets.only(right: 12.0)));
}
}
rightRowChildern.add(Padding(padding: EdgeInsets.only(right: 16.0)));
rightRowChildern = [
Row(
children: rightRowChildern,
)
];
}
var topBar = AppBar(
elevation: elevation,
brightness: Brightness.light,
backgroundColor: backgroundColor ?? Colors.white,
leading: leftmenuWidget ?? SizedBox(),
actions: rightRowChildern,
title: titleText,
centerTitle: centerTitle,
titleSpacing: 0,
);
return topBar;
}
//endregion
static String _getImageName({ButtontType type}) {
var iconName;
if (type == ButtontType.back) {
iconName = 'images/back.png';
} else if (type == ButtontType.menu) {
iconName = 'images/menu.png';
}
return iconName;
}
}
Now sample of How to use
// Appbar for notes page
final appBar = topBarWidget.createTopBar(
titleStyle: txtStyle,
title: "App Bar",
leftIcons: [ButtontType.back],
backgroundColor: Colors.white,
action: (ButtontType type) {
Navigator.of(context).pop();
});
var scaffold = Scaffold(
appBar: appBar,
body: scaffoldBuilder,
);
Hope this help!
Solution 3:[3]
Assuming you mean by respecting your theme that you want them to be white when your app bar is dark and vice versa, you just have to use brightness
attribute in the app bar
Eg:
AppBar(
backgroundColor: Color.fromARGB(1023, 255, 112, 5),
brightness: Brightness.dark,
title: Text(
'title',
),
)
or if you want to continue your work with what you have right now you can wrap your Icon with an Inkwell and you will get onTap to manage touches!
Solution 4:[4]
Ahem, all these answers are not really best practices.
Take and define a PrimaryIconTheme and that gets entered in two places in your AppBar Theme, i.e. iconTheme and actionsIconTheme
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | tjarvstrand |
Solution 2 | Dharmesh Mansata |
Solution 3 | Basel Abuhadrous |
Solution 4 | Fred Grott |