我很可能会错过一些东西,因为我很吵,但我发现ThemeData的选项非常有限(至少我对如何实现它的理解)。
如果你从MaterialUp看下面这个随机设计,我想要建立一些大致的东西:
Themedata.cyclingColor = Color.pink;
ThemeData.runningColor = Color.green;
在我的应用程序中,我可以参考骑行,跑步,游泳,健身房颜色(或者在我的应用程序/设计环境中有意义的任何颜色),并保持一致。
目前在Flutter中有推荐的方法吗?我有什么选择?
答案 0 :(得分:8)
我推荐这种方法,该方法很简单,可与热重载一起使用,并且可以轻松扩展以支持在黑暗和明亮主题之间切换。
首先创建您自己的类似于ThemeData
的模拟,我们将其称为AppThemeData
:
class AppThemeData {
final BorderRadius borderRadius = BorderRadius.circular(8);
final Color colorYellow = Color(0xffffff00);
final Color colorPrimary = Color(0xffabcdef);
ThemeData get materialTheme {
return ThemeData(
primaryColor: colorPrimary
);
}
}
只要需要标准materialTheme
,就可以使用ThemeData
。
然后创建一个名为AppTheme
的小部件,该小部件使用AppThemeData
包提供provider
的实例。
class AppTheme extends StatelessWidget {
final Widget child;
AppTheme({this.child});
@override
Widget build(BuildContext context) {
final themeData = AppThemeData(context);
return Provider.value(value: themeData, child: child);
}
}
最后,用AppTheme
包装整个应用程序。要访问主题,您可以调用context.watch<AppThemeData>()
。或创建此扩展程序...
extension BuildContextExtension on BuildContext {
AppThemeData get appTheme {
return watch<AppThemeData>();
}
}
...并使用context.appTheme
。我通常将final theme = context.appTheme;
放在小部件构建方法的第一行。
答案 1 :(得分:5)
我扩展了标准 ThemeData 以便在任何时候都可以像这样访问自己的主题字段:
Theme.of(context).own().errorShade
或者像这样:
ownTheme(context).errorShade
一个主题可以用如下的新字段定义和扩展(通过在某个 addOwn()
实例上调用的 ThemeData
):
final ThemeData lightTheme = (ThemeData.light().copyWith(
accentColor: Colors.grey.withAlpha(128),
backgroundColor: Color.fromARGB(255, 255, 255, 255),
textTheme: TextTheme(
caption: TextStyle(
fontSize: 17.0, fontFamily: 'Montserrat', color: Colors.black),
)))
..addOwn(OwnThemeFields(
errorShade: Color.fromARGB(240, 255, 200, 200),
textBaloon: Color.fromARGB(240, 255, 200, 200)));
final ThemeData darkTheme = ThemeData.dark().copyWith( ...
...
可以通过传统方式在 MaterialApp 小部件中设置后面的主题:
MaterialApp(
...
theme: lightTheme,
darkTheme: darkTheme,
)
这个想法是将主题化所需的所有自定义字段放在一个单独的类 OwnThemeFields
中。
然后使用 2 个方法扩展 ThemeData
类:
addOwn()
将 ThemedData
的某个实例连接到 OwnThemeFields
实例own()
允许查找与给定主题数据关联的自己的字段还可以创建 ownTheme
辅助方法来缩短对自己字段的提取。
class OwnThemeFields {
final Color errorShade;
final Color textBaloon;
const OwnThemeFields({Color errorShade, Color textBaloon})
: this.errorShade = errorShade,
this.textBaloon = textBaloon;
factory OwnThemeFields.empty() {
return OwnThemeFields(errorShade: Colors.black, textBaloon: Colors.black);
}
}
extension ThemeDataExtensions on ThemeData {
static Map<InputDecorationTheme, OwnThemeFields> _own = {};
void addOwn(OwnThemeFields own) {
_own[this.inputDecorationTheme] = own;
}
static OwnThemeFields empty = null;
OwnThemeFields own() {
var o = _own[this.inputDecorationTheme];
if (o == null) {
if (empty == null) empty = OwnThemeFields.empty();
o = empty;
}
return o;
}
}
OwnThemeFields ownTheme(BuildContext context) => Theme.of(context).own();
完整来源:https://github.com/maxim-saplin/dikt/blob/master/lib/ui/themes.dart
答案 2 :(得分:1)
您可以为系统类添加扩展名
仅添加实例属性很容易,但是如果您将获得动态颜色
您需要考虑一下。例如,使用常量在明暗模式下获取颜色
确定是否为暗模式
两种方式
MediaQuery.of(context).platformBrightnes == Brightness.dark;
Theme.of(context).brightness == Brightness.dark;
As you can see, you need the context, the context
为BuildContext添加扩展
这是代码
extension MYContext on BuildContext {
Color dynamicColor({int light, int dark}) {
return (Theme.of(this).brightness == Brightness.light)
? Color(light)
: Color(dark);
}
Color dynamicColour({Color light, Color dark}) {
return (Theme.of(this).brightness == Brightness.light)
? light
: dark;
}
/// the white background
Color get bgWhite => dynamicColor(light: 0xFFFFFFFF, dark: 0xFF000000);
}
使用方法
import 'package:flutter/material.dart';
import 'buildcontext_extension.dart';
class Test extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
color: context.bgWhite,
);
}
}
也
此颜色可能需要多个文件,因此您可以创建一个public.dart文件来管理所有内容
Like This
public.dart
library public;
// Export some common header files
// extensions
export 'buildcontext_extension.dart';
DarkMode图像支持
将浅色图像与深色图像归为同一类
some code
static String getImgPath(String name, {
String folder = '',
String format = 'png',
bool isDark = false,
bool needDark = true
}) {
String finalImagePath;
if (needDark) {
final folderName = isDark ? '${folder}_dark' : folder;
finalImagePath = 'assets/images/$folderName/$name.$format';
} else {
finalImagePath = 'assets/images/$folder/$name.$format';
}
String isDarkPath = isDark ? "? DarkMode" : "? LightMode";
print('$isDarkPath imagePath ? $finalImagePath');
return finalImagePath;
}
答案 3 :(得分:1)
使用此库 https://developers.googleblog.com/2017/12/creating-custom-estimators-in-tensorflow.html 进行主题切换。 并创建 ColorSheme 的扩展
extension MenuColorScheme on ColorScheme {
Color get menuBackground => brightness == Brightness.light
? InlLightColors.White
: InlDarkColors.Black;
}
在小部件中使用
Container(
color: Theme.of(context).colorScheme.menuBackground,
...
)
这种方式非常简单优雅。很高兴编码。
答案 4 :(得分:0)
您无法延长ThemeData
,因为物质组件再也找不到了。
除了Flutter中包含的MyThemeData
之外,你可以以同样的方式创建并提供ThemeData
。
创建一个扩展CustomThemeWidget
的小部件InheritedWidget
,并在那里提供您的自定义主题。
如果您想从当前主题中获取值
myTheme = CustomThemeWidget.of(context).myTheme;
要更改当前主题更改MyThemeData
CustomThemeWidget.myTheme
<强>更新强>
如https://github.com/flutter/flutter/pull/14793/files所示,应该可以通过覆盖ThemeData
来扩展ThemeData
并将其作为runtimeType
提供
另请参阅https://github.com/flutter/flutter/issues/16487#event-1573761656
中的评论答案 5 :(得分:0)
我还发现ThemeData
受到限制。我已经做过并且将来将要用于我所有应用程序的工作是创建自己的ThemeData
。
我创建了一个名为color_themes.dart
的文件,并创建了一个名为class
的{{1}},它的构造函数带有所需颜色的名称。例如ColorThemes
;
cyclingColor
然后可以通过导入文件并调用class ColorThemes {
const static cyclingColor = const Color(0xffb74093);
}
来调用这些颜色。可以在ColorThemes.cyclingColor
中分配这些值,以使这些颜色默认为ThemeData
。使用此方法的好处之一是,您不需要像这样{/ {1}}那样使用/引用ColorThemes
,从而使在提取的小部件中使用代码变得容易得多。
答案 6 :(得分:0)
现在可以通过使用Dart 2.7中的扩展方法来实现,请查看this article。
答案 7 :(得分:0)
如果不使用所有textTheme标题,这是一个简单的解决方法,您可以设置其中一些颜色并像通常使用其他颜色一样使用它们。
设置标题1的颜色:
ThemeData(textTheme: TextTheme(headline1: TextStyle(color: Colors.red),),),
使用它:
RawMaterialButton(fillColor: Theme.of(context).textTheme.headline1.color,onPressed: onPressed,)
答案 8 :(得分:0)
我创建了一个类似于 ThemeData
实现的实现:
@override
Widget build(BuildContext context) {
final Brightness platformBrightness = Theme.of(context).brightness;
final bool darkTheme = platformBrightness == Brightness.dark;
return CustomAppTheme(
customAppTheme:
darkTheme ? CustomAppThemeData.dark : CustomAppThemeData.light,
child: Icon(Icons.add, color: CustomAppTheme.of(context).addColor,),
);
}
import 'package:calendarflutter/style/custom_app_theme_data.dart';
import 'package:flutter/material.dart';
class CustomAppTheme extends InheritedWidget {
CustomAppTheme({
Key key,
@required Widget child,
this.customAppTheme,
}) : super(key: key, child: child);
final CustomAppThemeData customAppTheme;
static CustomAppThemeData of(BuildContext context) {
return context
.dependOnInheritedWidgetOfExactType<CustomAppTheme>()
.customAppTheme;
}
@override
bool updateShouldNotify(CustomAppTheme oldWidget) =>
customAppTheme != oldWidget.customAppTheme;
}
import 'package:flutter/material.dart';
class CustomAppThemeData {
final Color plusColor;
const CustomAppThemeData({
@required this.plusColor,
});
static CustomAppThemeData get dark {
return CustomAppThemeData(
plusColor: Colors.red,
);
}
static CustomAppThemeData get light {
return CustomAppThemeData(
plusColor: Colors.green,
);
}
}