扩展主题
此包可让您扩展Flutter中的**主题**,以便您可以定义和使用自己的属性。
它解决了什么问题?
假设您想为应用程序中的自定义小部件设置样式,但ThemeData中的属性并不完全符合您的需求。您宁愿添加自己的更具描述性的属性。
有几种方法可以做到这一点。
一种方法是为Theme创建扩展。但是,除非您开始在其中放置逻辑,否则它们不会如此动态。
另一种方法是创建您自己的Object,其中包含您的自定义样式,并像Theme一样通过InheritedWidget将它们提供给小部件树(或者您可以使用像provider这样的包)。
如果您只有一个样式,并且不支持浅色和深色主题,这就可以了。
但是,如果您确实想支持深色和浅色主题,并且您的应用程序有两个非常不同的部分应该使用自己的Theme,会发生什么?
您将得到
- 主主题浅色
- 主主题深色
- 主自定义主题浅色(用于自定义样式)
- 主自定义主题深色
- 次主题浅色
- 次主题深色
- 次自定义主题浅色
- 次自定义主题深色
这8个主题您需要跟踪,以便正确使用主题(主主题和次主题),以及这些主题的正确亮度(浅色/深色)变体。
您可能会得到16种不同的配置,而只有4种是有效的。
这正是扩展主题解决的问题。
它将采用默认的Theme,并将其与您的自定义属性合并到一个自定义主题中,这样您就不会混淆它们。
它是如何工作的?
扩展主题依赖于代码生成,根据您的自定义属性定义,创建一个全新的自定义主题,并提供所有必要的实用程序。
一个非常基础的定义示例
@ExtendedTheme()
abstract class _MyTheme {
Color get myCustomColor;
}
现在您可以在终端中运行以下命令
flutter pub run build_runner build
这将生成以下内容
- 一个名为
MyTheme的小部件(基于定义名称),您可以使用它,几乎与普通Theme小部件相同。事实上,这个小部件还将默认Theme添加到树中,因此每当您作用域MyTheme时,它都会使您的自定义属性和默认主题保持同步。 - 一个名为
MyThemeData的类,它将包含您的自定义属性以及默认的ThemeData。 - 一个名为
$MyTheme的InheritedWidget,它允许您在树中的任何位置获取MyThemeData。
如何使用它?
既然您已经有了自定义主题,就可以开始使用了。
定义您的主题
您只需像以前使用ThemeData一样定义您的主题。
final myLightTheme = MyThemeData(
themeData: ThemeData.light(),
myCustomColor: Colors.orange,
);
final myDarkTheme = MyThemeData(
themeData: ThemeData.dark(),
myCustomColor: Colors.red,
);
将扩展主题添加到树中
为了能够访问您的自定义属性,我们必须将MyTheme添加到树中。
通常,您会将ThemeData设置为MaterialApp的theme字段,这将其放在Navigator之上,并确保它在整个应用程序中可用。
我们不能只将MyThemeData放入theme字段,因为它不是ThemeData的子类。
要将MyTheme注入到MaterialApp Navigator之上,我们可以使用builder字段。
您可以手动执行此操作
return MaterialApp(
title: 'ExtendedTheme Demo',
builder: (context, child) => MyTheme(
light: myLightTheme,
dark: myDarkTheme,
child: child,
),
home: const Content(),
);
如果您注入其他小部件,这可能会很有用,或者您可以使用生成的便捷构建器
return MaterialApp(
title: 'ExtendedTheme Demo',
builder: MyTheme.builder(
light: myLightTheme,
dark: myDarkTheme,
),
home: const Content(),
);
如果您碰巧在应用程序中有多个独特的主题,如开头所述,您可以通过在需要它的地方将其添加到小部件树中,将MyTheme作用域限定到应用程序的特定部分。
return MyTheme(
light: mySecondaryLightTheme,
dark: mySecondaryDarkTheme,
child: SecondaryThemedPage(),
),
使用您的自定义属性
访问自定义属性就像
return Container(
color: MyTheme.of(context).myCustomColor,
);
ExtendedThemeData
在我们之前的例子中,我们只使用了一个简单的属性。
但是,如果我们想为自定义小部件添加样式怎么办?
就像ExtendedTheme一样,您可以定义ExtendedThemeData。
假设我们有一个自定义小部件,它有几个属性
@ExtendedThemeData
abstract class _MyWidget {
Color get backgroundColor;
Color get foregroundColor;
double? get width;
double? get height;
BoxShape get shape;
}
这将生成一个名为MyThemeData的类,它将包含我们定义的属性和一个适当的构造函数。
待办事项
- 添加方便的copyWith、merge等方法
- 添加默认值