如何更改 NavigationBar 内字体的颜色?

作者站长头像
站长
· 阅读数 7

我要的不是改变 bottomNavigationBar 或 NavigationBar的背景色,而是想改以下代码 label(图标下面的文本字体)颜色

import 'package:flutter/material.dart';

void main() => runApp(const ExampleApp());

class ExampleApp extends StatelessWidget {
  const ExampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(home: NavigationExample());
  }
}

class NavigationExample extends StatefulWidget {
  const NavigationExample({super.key});

  @override
  State<NavigationExample> createState() => _NavigationExampleState();
}

class _NavigationExampleState extends State<NavigationExample> {
  int currentPageIndex = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      bottomNavigationBar: NavigationBar(
        onDestinationSelected: (int index) {
          setState(() {
            currentPageIndex = index;
          });
        },
        selectedIndex: currentPageIndex,
        destinations: const <Widget>[
          NavigationDestination(
            icon: Icon(Icons.explore),
            label: 'Explore',
          ),
          NavigationDestination(
            icon: Icon(Icons.commute),
            label: 'Commute',
          ),
          NavigationDestination(
            selectedIcon: Icon(Icons.bookmark),
            icon: Icon(Icons.bookmark_border),
            label: 'Saved',
          ),
        ],
      ),
      body: <Widget>[
        Container(
          color: Colors.red,
          alignment: Alignment.center,
          child: const Text('Page 1'),
        ),
        Container(
          color: Colors.green,
          alignment: Alignment.center,
          child: const Text('Page 2'),
        ),
        Container(
          color: Colors.blue,
          alignment: Alignment.center,
          child: const Text('Page 3'),
        ),
      ][currentPageIndex],
    );
  }
}
回复
1个回答
avatar
test
2024-07-08

运行一下看是否满足需求

import 'package:flutter/material.dart';

void main() => runApp(const ExampleApp());

class ExampleApp extends StatelessWidget {
  const ExampleApp({super.key});

  NavigationBarThemeData _naviBarThemeData() {
    late MaterialStateProperty<IconThemeData?> iconThemeData;
    late MaterialStateProperty<TextStyle?> labelTextStyle;

    iconThemeData =
        MaterialStateProperty.resolveWith((Set<MaterialState> states) {
      if (states.isEmpty) {
         //没有选中的状态下state为空
        return const IconThemeData(size: 24, color: Colors.red);
      } else if (states.contains(MaterialState.selected)) {
        return const IconThemeData(size: 24, color: Colors.amber);
      }
      return null;
    });

    labelTextStyle =
        MaterialStateProperty.resolveWith((Set<MaterialState> states) {
      if (states.isEmpty) {
        //没有选中的状态下state为空
        return const TextStyle(color: Colors.red, fontSize: 24);
      } else if (states.contains(MaterialState.selected)) {
        return const TextStyle(color: Colors.amber, fontSize: 24);
      }
      return null;
    });

    return NavigationBarThemeData(
        iconTheme: iconThemeData, labelTextStyle: labelTextStyle);
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        theme: ThemeData(navigationBarTheme: _naviBarThemeData()),
        home: const NavigationExample());
  }
}

class NavigationExample extends StatefulWidget {
  const NavigationExample({super.key});

  @override
  State<NavigationExample> createState() => _NavigationExampleState();
}

class _NavigationExampleState extends State<NavigationExample> {
  int currentPageIndex = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      bottomNavigationBar: NavigationBar(
        onDestinationSelected: (int index) {
          setState(() {
            currentPageIndex = index;
          });
        },
        selectedIndex: currentPageIndex,
        destinations: const <Widget>[
          NavigationDestination(
            icon: Icon(Icons.explore),
            label: 'Explore',
          ),
          NavigationDestination(
            icon: Icon(Icons.commute),
            label: 'Commute',
          ),
          NavigationDestination(
            selectedIcon: Icon(Icons.bookmark),
            icon: Icon(Icons.bookmark_border),
            label: 'Saved',
          ),
        ],
      ),
      body: <Widget>[
       
        Container(
          color: Colors.red,
          alignment: Alignment.center,
          child: const Text('Page 1'),
        ),
        Container(
          color: Colors.green,
          alignment: Alignment.center,
          child: const Text('Page 2'),
        ),
        Container(
          color: Colors.blue,
          alignment: Alignment.center,
          child: const Text('Page 3'),
        ),
      ][currentPageIndex],
    );
  }
}

如何找到这个解决方法

查看文档.repeat(until_you_solve) 😂 😂

  1. 首先想到查看 NavigationBar 构造函数中有没有可以设置icon,label的颜色,大小的属性,在IDE中通过 点击鼠标左键NavigationBar的同时按住windows健或者Command健打开,好像有一个backgroundColor但是这个是改变背景色的

    NavigationBar(
     { Key? key, 
       Duration? animationDuration, 
       int selectedIndex = 0, 
       required List<Widget> destinations, 
       ValueChanged<int>? onDestinationSelected, 
       Color? backgroundColor, 
       double? elevation, 
       Color? shadowColor, 
       Color? surfaceTintColor, 
       double? height, 
       NavigationDestinationLabelBehavior? labelBehavior
    })
  2. 继续查看 NavigationDestination 构造函数有没有可以设置icon,label的颜色,大小的属性,并也没有

    NavigationDestination(
     {Key? key, 
      required Widget icon, 
      Widget? selectedIcon, 
      required String label, 
      String? tooltip
    })
  3. 即然 NavigationDestination 没有改变大小,颜色的属性,继续查看其icon属性,label属性的使用说明,icon属性使用说明如下

     /// The [Widget] (usually an [Icon]) that's displayed for this
     /// [NavigationDestination].
     ///
     /// The icon will use [NavigationBarThemeData.iconTheme]. If this is
     /// null, the default [IconThemeData] would use a size of 24.0 and
     /// [ColorScheme.onSurface].
     final Widget icon;
    

    上面的icon属性会优先使用NavigationBarThemeData.iconTheme 来设置icon,

    如果NavigationBarThemeData.iconTheme为null,那么使用默认的IconThemeData来设置icon大小与颜色,icon的大小是24,颜色为ColorScheme.onSurface

    给的解决方法中通过设置 NavigationBarThemeData.iconTheme 来配置icon大小的与颜色,贰 NavigationBarThemeData是在MaterialApp中进行配置的

源码中的设置

 buildIcon: (BuildContext context) {
        final Widget selectedIconWidget = IconTheme.merge(
            //在这里进行设置
          data: navigationBarTheme.iconTheme?.resolve(selectedState)
            ?? defaults.iconTheme!.resolve(selectedState)!,
          child: selectedIcon ?? icon,
        );
        final Widget unselectedIconWidget = IconTheme.merge(
          data: navigationBarTheme.iconTheme?.resolve(unselectedState)
            ?? defaults.iconTheme!.resolve(unselectedState)!,
          child: icon,
        );

        return Stack(
          alignment: Alignment.center,
          children: <Widget>[
            NavigationIndicator(
              animation: animation,
                //猜猜这是什么作用?配置一下试试
              color: navigationBarTheme.indicatorColor ?? defaults.indicatorColor!,
              shape: navigationBarTheme.indicatorShape ?? defaults.indicatorShape!
            ),
            _StatusTransitionWidgetBuilder(
              animation: animation,
              builder: (BuildContext context, Widget? child) {
                return _isForwardOrCompleted(animation)
                  ? selectedIconWidget
                  : unselectedIconWidget;
              },
            ),
          ],
        );
      },

其他

  • NavigationBar的 destinations的参数类型是 List <Widget> ,也根据自己需要完全自定义
  • 对于某个组件用法可以看官方给出的demo(如果有),还有源码(感谢开源🙏🙏🙏),如果组件不满足自己也可根据需求进行修改
  • 你觉得这条该是什么?

参考

A-demo-for-material—state-property

回复
likes
适合作为回答的
  • 经过验证的有效解决办法
  • 自己的经验指引,对解决问题有帮助
  • 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
  • 询问内容细节或回复楼层
  • 与题目无关的内容
  • “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容