如何在Flutter中设置AppBar操作按钮的颜色

6

我尝试使用主题来设置我的AppBar操作图标的颜色,但出于某些原因它并没有生效。以下是我的最小代码示例:

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))
        ]
      )
    ));
  }
}
  • iconTheme颜色值均无效。
  • MaterialApp.iconThemeAppBar.iconThemeAppBar.actionsIconTheme中设置不透明度实际上会生效。
  • 显式设置Icon.color是可行的,但我认为我不应该这样做,对吗?

如何让IconButton遵循我的主题?

谢谢 Thomas

编辑:通过直接使用Icon而不是IconButton,我确实能够使图标遵守我的主题,但是我如何使其可点击?根据https://api.flutter.dev/flutter/material/AppBar/actions.htmlIconButton是在AppBar.actions中使用最常见的小部件。这是不正确的吗?

4个回答

10

所以,显然我的问题是我没有定义 IconButtononPressed 属性。一旦我添加了这个属性,我的主题就被正确应用了。

我知道这是一个必需的属性,但在构建/运行应用程序时我没有收到任何错误提示。


2
请注意:将任何类型的按钮的 onPressed 属性设置为 null,它将被禁用并呈禁用样式(您可以尝试使用基本的 RaisedButton)。我个人在使用 UI 中的每个按钮时首先编写 onPressed: (){} - Augustin R
我讨厌“null”。 - tjarvstrand
1
很遗憾,有时回调函数的默认值就是这样。 - Augustin R
是的 :/ 不过谢谢你的提示! - tjarvstrand

1

创建一个通用的应用栏小部件类

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;
  }
}

现在是关于如何使用的示例。
// 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,
    );

希望这可以帮到您!

0
啊,所有这些答案都不是最佳实践。
定义一个PrimaryIconTheme,并将其输入到AppBar主题的两个位置中,即iconTheme和actionsIconTheme。

0

假设您所说的尊重您的主题是指当您的应用栏为暗色时,您希望它们为白色,反之亦然,则只需在应用栏中使用属性即可。

例如:

AppBar(
  backgroundColor: Color.fromARGB(1023, 255, 112, 5),
  brightness: Brightness.dark,
  title: Text(
    'title',
  ),
)

或者,如果您想继续使用当前的内容进行工作,您可以使用Inkwell包装您的图标,这样您就可以使用onTap来管理触摸操作!


哦,设置“亮度”也没有效果。我对此还很陌生,但目前AppBar标题和我添加到栏中的任何Drawer图标都是白色的,而IconButton是灰色的。我希望它们全部都是相同的颜色。我只是写了“尊重我的主题”,因为我认为这就是标题和抽屉图标颜色(白色)的来源。 - tjarvstrand
请尽量轻松而不是沉闷。 - Basel Abuhadrous
仍然没有任何变化,恐怕无法满足您的要求。 - tjarvstrand
尽管小部件变得更小并且靠近屏幕边缘,但它似乎工作正常。 - tjarvstrand
尝试对其进行操作,例如将其放置在列或容器中,甚至更改其大小可能会有所帮助。 - Basel Abuhadrous
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接