'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 or AppBar.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