flutter 全局主题

本文最后更新于:2022年4月22日 上午

flutter 全局主题

可以通过配置一些全局属性来使一些 widget拥有默认的样式。

例如 亮色/暗黑模式,默认的字体大小,h1-h6的字体大小,buttonswitch的颜色等

theme

MaterialApp的参数中可以通过 theme中配置全局的主题

如下配置

return MaterialApp(
  debugShowCheckedModeBanner: false,
  home: HomePage(),
  theme: ThemeData(
    // 亮色,暗色 模式
    brightness: Brightness.dark,

    // primaryColor: Colors.green,
    // 主色调
    primarySwatch: Colors.red,

    // 按钮主题
    buttonTheme: ButtonThemeData(minWidth: 20, height: 10, buttonColor: Colors.amber),
    elevatedButtonTheme: ElevatedButtonThemeData(
      style: ButtonStyle(
          backgroundColor: MaterialStateProperty.resolveWith(getButtonColor),
          // 配置按钮最小宽高
          minimumSize: MaterialStateProperty.all(Size(25, 20))),
    ),

    textTheme: TextTheme(
      // app 默认的文字大小
      bodyText2: TextStyle(fontSize: 14),

      bodyText1: TextStyle(fontSize: 16),

      // h1
      headline1: TextStyle(fontSize: 96),
      headline2: TextStyle(fontSize: 60),

      button: TextStyle(color: Colors.green),
    ),
  ),

  // 暗黑模式下的主题,实战中会将主题单独抽离
  darkTheme: ThemeData(
    primarySwatch: Colors.green,
    scaffoldBackgroundColor: Colors.white38,
  ),
  // themeMode: ThemeMode,
);

brightness 亮色/暗黑模式

值是一个枚举值,用来控制亮色/暗黑模式,Brightness.dark/Brightness.light

primarySwatch 主色

用来配置全局主色调,它的值不能是一个普通的Color类,需要是一个 MaterialColor类型,一共有 [50 - 900]的值,通过 Colors.res[200]的方式来指定获取某个颜色,因为 重写了 [] 操作符

并不是所有的颜色都是 MaterialColor,例如黑色就不是

buttonTheme 按钮主题

用来配置默认的按钮主题

buttonTheme: ButtonThemeData(minWidth: 20, height: 10, buttonColor: Colors.amber),

flutter 1.22更新后新增了 ElevatedButton等按钮,可以单独配置的它的主题

更新日志 https://juejin.cn/post/6879048672597213198

配置参考https://blog.vini123.com/600

Color getButtonColor(Set<MaterialState> states) {
  const Set<MaterialState> interactiveStates = <MaterialState>{
    MaterialState.pressed,
    MaterialState.hovered,
    MaterialState.focused,
  };

  // 如果是 interactiveStates 包含的状态,则返回红色
  if (states.any((element) => interactiveStates.contains(element))) {
    return Colors.red[600]!;
  }
  return Colors.red;
}

 elevatedButtonTheme: ElevatedButtonThemeData(
    style: ButtonStyle(
        backgroundColor: MaterialStateProperty.resolveWith(getButtonColor),
        // 配置按钮最小宽高
        minimumSize: MaterialStateProperty.all(Size(25, 20))),
  ),

textTheme 文字样式

配置默认的字体大小,颜色等

默认使用的文字是 body2

NAME         SIZE  WEIGHT  SPACING
headline1    96.0  light   -1.5
headline2    60.0  light   -0.5
headline3    48.0  regular  0.0
headline4    34.0  regular  0.25
headline5    24.0  regular  0.0
headline6    20.0  medium   0.15
subtitle1    16.0  regular  0.15
subtitle2    14.0  medium   0.1
body1        16.0  regular  0.5   (bodyText1)
body2        14.0  regular  0.25  (bodyText2)
button       14.0  medium   1.25
caption      12.0  regular  0.4
overline     10.0  regular  1.5

配置

textTheme: TextTheme(
  // app 默认的文字大小
  bodyText2: TextStyle(fontSize: 14),

  bodyText1: TextStyle(fontSize: 16),

  // h1
  headline1: TextStyle(fontSize: 96),
  headline2: TextStyle(fontSize: 60),

  button: TextStyle(color: Colors.green),
),

darkTheme 暗色模式

通过单独配置 darkTheme来修改暗色模式下的颜色

// 暗黑模式下的主题
darkTheme: ThemeData(
  primarySwatch: Colors.green,
  scaffoldBackgroundColor: Colors.white38,
),

使用配置的主题

通过 Theme.of(context).textTheme获取全局主题

通过Theme.of(context).textTheme.headline2!.copyWith(color: Colors.green))来在全局的主题配置的基础上进行修改

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(title: Text('主题配置')),
    body: Center(
      child: Column(
        children: [
          Text('h1标题', style: Theme.of(context).textTheme.headline1),
          Text('h2标题', style: Theme.of(context).textTheme.headline2),
          Text('h2标题 修改颜色', style: Theme.of(context).textTheme.headline2!.copyWith(color: Colors.green)),
          Text('默认字体'),
          Text('默认字体 body1', style: Theme.of(context).textTheme.bodyText1),
          ElevatedButton(onPressed: () {}, child: Text('按钮')),
          Switch(value: true, onChanged: (val) {}),
          CupertinoSwitch(value: true, onChanged: (val) {})
        ],
      ),
    ),
    floatingActionButton: FloatingActionButton(
      child: Icon(Icons.add),
      onPressed: () {},
    ),
    // body: Text('home'),
  );
}

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议,转载请注明出处。