Flutter 主题:具有自定义颜色的浅色和深色主题
际项目中,我们需要为我们的应用程序品牌添加自定义颜色。
在这篇博客中,我们将逐步分享如何创建一个 flutter 自定义主题
使用自定义颜色的 Flutter 主题分步指南
要成功实施 Flutter 主题化,您必须满足以下先决条件:
创建颤振项目
在 yaml 中添加 riverpod 包(注意:您可以根据自己的方便使用任何状态管理包)
准备好继续操作后,请连续执行以下步骤以启用自定义 Flutter 主题。
想要实现自定义选项以在您的应用程序中动态更改主题?
聘请Bacancy 的 Flutter 开发人员为您的应用品牌添加或自定义主题颜色
第 1 步:创建浅色/深色主题
为了创建明暗模式的主题,我们使用 ThemeData 类并根据需要自定义颜色和其他属性。我们已经创建了一种基于选定的浅色/深色主题获取 ThemeDate 的方法。
我们根据所选主题为 scaffoldBackgroundColor、bodyColor、thumbColor、listTileTheme 和 appBarTheme 赋予不同的值。
ThemeData getAppTheme(BuildContext context, bool isDarkTheme) {
返回主题数据(
scaffoldBackgroundColor: isDarkTheme ? 颜色.black : 颜色.white,
文本主题:Theme.of(context)
.text主题
.copyWith(
标题小:
Theme.of(context).textTheme.titleSmall?.copyWith(fontSize: 11),
)
。申请(
bodyColor: isDarkTheme ? 颜色.white : 颜色.black,
显示颜色:Colors.grey,
),
切换主题:切换主题数据(
thumbColor: MaterialStateProperty.all(
是深色主题吗?颜色.橙色 : 颜色.紫色),
),
listTileTheme: ListTileThemeData(
iconColor: isDarkTheme ? 颜色.橙色 : 颜色.紫色),
appBarTheme: AppBarTheme(
backgroundColor: isDarkTheme ? 颜色.black : 颜色.white,
图标主题:
IconThemeData(颜色:isDarkTheme?Colors.white:Colors.black54)),
);}
第 2 步:使用 River-pod 为主题状态创建提供者
我们将使用 river-pod 来管理应用主题状态。我们只想存储 bool 值来管理浅色或深色主题,因此我们将使用 StateProvider。
第 3 步:在 App 中使用主题
我们在项目中使用 river-pod,因此我们必须使用 ProviderScope 包装 MyApp 以访问所有提供程序的 though-out 应用程序。MyApp 扩展了 ConsumerWidget,因此我们可以在构建方法中获取 WidgetRef 对象,并使用 ref 变量访问任何 river-pod。getAppTheme(context, ref.watch(appThemeProvider))方法监听应用主题的任何变化并相应地更新应用。
类 MyApp 扩展 ConsumerWidget {
const MyApp({super.key});
@覆盖
小部件构建(BuildContext 上下文,WidgetRef ref){
返回 MaterialApp(
title: 'Flutter Light/Dark Theme',
debugShowCheckedModeBanner: false,
主题:getAppTheme(上下文,ref.watch(appThemeProvider)),
主页:const MyHomePage(),
);
}}
ref.read(appThemeProvider.notifier).state = value。当切换状态从浅色/深色状态更改时,我们正在更新 appThemeProvider 中的主题状态。
转变(
activeColor: Colors.orange,
onChanged:(值){
ref.read(appThemeProvider.notifier).state = value;
},
值:isDarkMode)
第 4 步:添加自定义颜色
它工作正常,因为它会在所有图标和文本中显示相同的颜色。如果我们想在图标上使用不同的颜色,我们必须为主题创建一个扩展。创建一个类并使用 ThemeExtension 进行扩展,并添加您想要自定义的必要字段。
AppColors 类扩展 ThemeExtension<AppColors> {
最终颜色?颜色1;
最终颜色?颜色2;
最终颜色?颜色3;
常量 AppColors({
需要this.color1,
需要this.color2,
需要this.color3,
});
@覆盖
AppColors copyWith({
颜色?颜色1,
颜色?颜色2,
颜色?颜色3,
}) {
返回 AppColors(
颜色 1:颜色 1 ?? 这个.color1,
颜色 2:颜色 2 ?? 这个.color2,
颜色 3:颜色 3 ?? 这个.color3,
);
}
@覆盖
AppColors lerp(ThemeExtension<AppColors>? other, double t) {
如果(其他是!AppColors){
归还这个;
}
返回 AppColors(
color1: Color.lerp(color1, other.color1, t),
color2: Color.lerp(color2, other.color2, t),
color3: Color.lerp(color3, other.color3, t),
);
}}
现在在我们的创建方法 getAppTheme 中的 ThemeData 中添加这个扩展属性,并根据颜色定义主题。
扩展:<ThemeExtension<AppColors>>[
应用颜色(
color1: isDarkTheme ? 颜色.blue : 颜色.blueGrey,
color2: isDarkTheme ? 颜色.pink : Colors.pinkAccent,
color3: isDarkTheme ? Colors.yellow : Colors.limeAccent,
),
创建我们用来轻松访问自定义颜色的另一个扩展函数。
我们可以简单地使用colors(context).color1访问小部件中的这些颜色。如果我们不指定图标颜色,它将从 listTileTheme 中获取颜色。
列表块(
前导:图标(Icons.chat_outlined,颜色:颜色(上下文).color3),
title: Text( "帮助中心", style: Theme.of(context).textTheme.titleSmall),
),列表块(
前导:const Icon(Icons.notifications),
title: Text("Notification", style: Theme.of(context).textTheme.titleSmall),),
第 5 步:完整源代码
这是主题类的代码:
导入“包:flutter/material.dart”;AppColors 颜色(上下文)=> Theme.of(上下文).extension<AppColors>()!;ThemeData getAppTheme(BuildContext context, bool isDarkTheme) {
返回主题数据(
扩展:<ThemeExtension<AppColors>>[
应用颜色(
color1: isDarkTheme ? 颜色.blue : 颜色.green,
color2: isDarkTheme ? 颜色.pink : 颜色.blue,
color3: isDarkTheme ? 颜色.黄色:颜色.红色,
),
],
scaffoldBackgroundColor: isDarkTheme ? 颜色.black : 颜色.white,
文本主题:Theme.of(context)
.text主题
.copyWith(
标题小:
Theme.of(context).textTheme.titleSmall?.copyWith(fontSize: 12),
)
。申请(
bodyColor: isDarkTheme ? 颜色.white : 颜色.black,
显示颜色:Colors.grey,
),
切换主题:切换主题数据(
thumbColor: MaterialStateProperty.all(
是深色主题吗?颜色.橙色 : 颜色.紫色),
),
listTileTheme: ListTileThemeData(
iconColor: isDarkTheme ? 颜色.橙色 : 颜色.紫色),
appBarTheme: AppBarTheme(
backgroundColor: isDarkTheme ? 颜色.black : 颜色.white,
图标主题:
IconThemeData(颜色:isDarkTheme?Colors.white:Colors.black54)),
);}@immutableAppColors 类扩展 ThemeExtension<AppColors> {
最终颜色?颜色1;
最终颜色?颜色2;
最终颜色?颜色3;
常量 AppColors({
需要this.color1,
需要this.color2,
需要this.color3,
});
@覆盖
AppColors copyWith({
颜色?颜色1,
颜色?颜色2,
颜色?颜色3,
}) {
返回 AppColors(
颜色 1:颜色 1 ?? 这个.color1,
颜色 2:颜色 2 ?? 这个.color2,
颜色 3:颜色 3 ?? 这个.color3,
);
}
@覆盖
AppColors lerp(ThemeExtension<AppColors>? other, double t) {
如果(其他是!AppColors){
归还这个;
}
返回 AppColors(
color1: Color.lerp(color1, other.color1, t),
color2: Color.lerp(color2, other.color2, t),
color3: Color.lerp(color3, other.color3, t),
);
}}
这是我们主屏幕的代码:
导入“包:flutter/material.dart”;导入“包:flutter_riverpod/flutter_riverpod.dart”;导入“包:light_dark_mode/provider%20/app_theme_provider.dart”;导入“包:light_dark_mode/utils/app_theme.dart”;无效主要(){
runApp(const ProviderScope(child: MyApp()));}类 MyApp 扩展 ConsumerWidget {
const MyApp({super.key});
@覆盖
小部件构建(BuildContext 上下文,WidgetRef ref){
返回 MaterialApp(
title: 'Flutter Light/Dark Theme',
debugShowCheckedModeBanner: false,
主题:getAppTheme(上下文,ref.watch(appThemeProvider)),
主页:const MyHomePage(),
);
}}类 MyHomePage 扩展 ConsumerWidget {
const MyHomePage({Key?key}) : super(key: key);
@覆盖
小部件构建(BuildContext 上下文,WidgetRef ref){
var isDarkMode = ref.watch(appThemeProvider);
返回脚手架(
应用栏:应用栏(
海拔:0,
前导:const Icon(Icons.arrow_back_ios_sharp),
动作:常量 [
填充(
填充:EdgeInsets.symmetric(水平:15.0),
孩子:图标(Icons.add_circle_outline),
)
],
),
身体:填充(
填充:const EdgeInsets.symmetric(水平:8.0),
孩子:列表视图(
孩子们: [
圆形头像(
半径:60,
背景颜色:Colors.grey,
孩子:填充(
padding: const EdgeInsets.all(1), // 边框半径
孩子:ClipRRect(
borderRadius: BorderRadius.circular(60),
孩子:Image.asset(
“资产/ic_profile.jpeg”,
适合:BoxFit.fill,
宽度:120,
身高:120,
)),
),
),
容器(
保证金:const EdgeInsets.only(顶部:10,底部:60),
对齐方式:Alignment.center,
孩子:文本(
“测试用户”,
风格:Theme.of(context).textTheme.titleLarge,
),
),
列表块(
前导:图标(isDarkMode ? Icons.brightness_3 : Icons.sunny),
标题:文本(
是黑暗模式吗?“深色模式”:“浅色模式”,
风格:Theme.of(context).textTheme.titleSmall,
),
尾随:消费者(建造者:(上下文,参考,孩子){
返回 Transform.scale(
规模:0.7,
孩子:开关(
activeColor: Colors.orange,
onChanged:(值){
ref.read(appThemeProvider.notifier).state = value;
},
值:isDarkMode,
),
);
}),
),
列表块(
领先:图标(Icons.grid_on_sharp,颜色:颜色(上下文)。color1,),
标题:文本(
“故事”,
风格:Theme.of(context).textTheme.titleSmall,
),
),
列表块(
领先:图标(图标。设置,颜色:颜色(上下文)。颜色2),
title: Text("设置和隐私",
样式:Theme.of(context).textTheme.titleSmall),
),
列表块(
前导:图标(Icons.chat_outlined,颜色:颜色(上下文).color3),
标题:文本(
“帮助中心”,
风格:Theme.of(context).textTheme.titleSmall,
),
),
列表块(
前导:const Icon(Icons.notifications),
标题:文本(
“通知”,
风格:Theme.of(context).textTheme.titleSmall,
),
),
],
),
),
);
}}
您可以在此处找到完整代码:GitHub 存储库。
结论
我希望这篇博客能帮助您定制您的 Flutter 应用主题。在这篇博客中,我们在 ThemeExtension 中自定义了 Colors;但是,我们可以使用任何字段来自定义值。Flutter 主题化只是一方面,我们还提供了其他几种解决方案,您可以在Flutter 教程上找到这些解决方案。
(言鼎科技)