您当前的位置:易学堂 > 运维教程

flutter中如何使用和扩展ThemeData实现详解

时间:2022-11-16 09:55:13

做过UI开发的同学都知道,在开发中我们通常会将 文字大小、色值 等内容放在配置文件中,通过统一的管理类来读取(严禁在UI代码中写死)。以便后续调整时不用修改源码,只需要修改配置文件即可。

例如这样:

  • 定义常量存放

/// 存放颜色常量
abstract class ColorConfigs {
  static const Color background = Color(0xFFFF6600);
  static const Color textHint = Color(0xFFA0A4A7);
}
  • 通过统一获取

/// GOOD
Container(
  //通过 ColorConfig 获取色值
  color: ColorConfigs.background,
)
/// BAD
Container(
  //写死
  color: Color(0xFFFF6600),
)

Flutter为我们提供了Theme类,可以让我们节省封装常量配置类(如上示例中的 ColorConfigs)的步骤。将色值、字体风格等配置内容存入ThemeData中,子控件可统一通过 Theme.of(context)读取 color、textStyle、等配置信息。

本篇通过换肤demo,介绍在flutter项目中如何使用 theme 以及如何对 themeData 进行字段扩展,实现全局的主题配置管理。

Theme 的基本使用方式

1. Theme 的注册

MaterialApp(
  theme: myThemeData, //一个ThemeData的实例,下面提供具体代码
  home: BodyWidget(),
)

我们做全局的主体配置,在 MaterialApp 中对 theme 字段进行入参赋值。示例代码中的 myThemeData 是一个 ThemeData 的实现实例,可通过 ThemeData 的构造方法来查看其可供保存的主体及样式信息,按照各自所需进行参数赋值。

下面是小编在自己项目中用到的ThemeData配置项,定义了各种状态颜色、字体样式、可供参考:

myThemeData

val myThemeData = ThemeData(
  primaryColor: Colors.white,
  disabledColor: const Color(0xffcbced0),
  backgroundColor: const Color(0xfff3f4f5),
  hintColor: const Color(0xffe2e5e7),
  errorColor: const Color(0xffe21a1a),
  highlightColor: const Color(0xffa7d500),
  shadowColor: const Color(0xffa0a4a7),
  selectedRowColor: const Color(0xfff3f4f5),
  colorScheme: const ColorScheme.light(
primary: Colors.white,
secondary: Color(0xffa7d500),
background: Color(0xfff3f4f5),
error: Color(0xffe21a1a),
onPrimary: Color(0xff242524),
onError: Colors.white,
onBackground: Color(0xffe2e5e7),
onSecondary: Color(0xff707275),
  ),
  textTheme: TextTheme(
headline1: TextStyle(
  fontSize: 17.sp,
  fontWeight: FontWeight.bold,
  color: const Color(0xff242524),
),
headline2: TextStyle(
  fontSize: 16.sp,
  fontWeight: FontWeight.bold,
  color: const Color(0xff242524),
),
...中间省略 healin3 ~ headline5,只是配置不一样
headline6: TextStyle(
  fontSize: 14.sp,
  fontWeight: FontWeight.bold,
  color: const Color(0xff707275),
),
subtitle1: TextStyle(
  fontSize: 12.sp,
  fontWeight: FontWeight.w500,
  color: const Color(0xff242524),
),
subtitle2: TextStyle(
  fontSize: 12.sp,
  fontWeight: FontWeight.w500,
  color: const Color(0xff707275),
),
bodyText1: TextStyle(
  fontSize: 11.sp,
  fontWeight: FontWeight.normal,
  color: const Color(0xff242524),
),
bodyText2: TextStyle(
  fontSize: 11.sp,
  fontWeight: FontWeight.normal,
  color: const Color(0xff242524),
),
  ),
)

2. 读取 ThemeData 里的配置:

@override
Widget build(BuildContext context) {
  return Container(
color: Theme.of(context).backgroundColor,
child: Text(
'hellow', 
style: Theme.of(context).headline).bodyText1,
  );
}
  • Theme.of(context).backgroundColor:读取主题配置中的背景颜色,在 myThemeData 中进行过赋值操作

  • Theme.of(context).headline).bodyText1:读取主题配置中键值为 bodyText1 的字体样式

小技巧介绍

通常为了便于开发阅读,我们也可以使用extension对 ThemeData 内属性进行重命名获取:

新建 extension_theme.dart,文件名字随意:

///用于重命名颜色属性
extension ThemeDataColorExtension on ThemeData {
  Color get bgColor => colorScheme.onBackground;
 ...
}
///用于重命名字体样式属性
extension ThemeDataTextStyleExtension on ThemeData {
  TextStyle get bodyStyle => textTheme.bodyText1!;
 ...
}

在UI页面进行引用导入使用,上面的 demo 可改为:

import ./extension_theme.dart
...
@override
Widget build(BuildContext context) {
  return Container(
color: Theme.of(context).bgColor,
child: Text(
'hellow', 
style: Theme.of(context).bodyStyle,
  );
}

ThemeData 内置字段不够用,如何扩展?

从 ThemeData 的构造函数中我们可以看到,ThemeData 内置的字段是有限的。假如我们的UI设计包含的色值数量或者字体样式数量超出了 ThemeData 可供设置数量怎么办呢?

比如:我们想新增一个色值配置,名字就叫 connerColor,我们还想保持统一,一律通过 ThemeData 来统一读取统一配置,要如何处理呢?

小编在项目里是这么做的,将 ThemeData 进行一层封装,以新增 connerColor 为例,具体代码结合下面

标签: flutterThemeData