Flutter 主题:具有自定义颜色的浅色和深色主题

言鼎科技 2023-05-25 382

际项目中,我们需要为我们的应用程序品牌添加自定义颜色。

在这篇博客中,我们将逐步分享如何创建一个 flutter 自定义主题

Flutter 主题:具有自定义颜色的浅色和深色主题

使用自定义颜色的 Flutter 主题分步指南

要成功实施 Flutter 主题化,您必须满足以下先决条件:

  • 创建颤振项目

  • 在 yaml 中添加 riverpod 包(注意:您可以根据自己的方便使用任何状态管理包)

准备好继续操作后,请连续执行以下步骤以启用自定义 Flutter 主题。

想要实现自定义选项以在您的应用程序中动态更改主题?
聘请Bacancy 的 Flutter 开发人员为您的应用品牌添加或自定义主题颜色

第 1 步:创建浅色/深色主题

为了创建明暗模式的主题,我们使用 ThemeData 类并根据需要自定义颜色和其他属性。我们已经创建了一种基于选定的浅色/深色主题获取 ThemeDate 的方法。

我们根据所选主题为 scaffoldBackgroundColor、bodyColor、thumbColor、listTileTheme 和 appBarTheme 赋予不同的值。

Flutter 主题:具有自定义颜色的浅色和深色主题
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。

Flutter 主题:具有自定义颜色的浅色和深色主题
final appThemeProvider = StateProvider<bool>((ref) => false);

第 3 步:在 App 中使用主题

我们在项目中使用 river-pod,因此我们必须使用 ProviderScope 包装 MyApp 以访问所有提供程序的 though-out 应用程序。MyApp 扩展了 ConsumerWidget,因此我们可以在构建方法中获取 WidgetRef 对象,并使用 ref 变量访问任何 river-pod。getAppTheme(context, ref.watch(appThemeProvider))方法监听应用主题的任何变化并相应地更新应用。

Flutter 主题:具有自定义颜色的浅色和深色主题
类 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 中的主题状态。

Flutter 主题:具有自定义颜色的浅色和深色主题
转变(
 activeColor: Colors.orange,
 onChanged:(值){
   ref.read(appThemeProvider.notifier).state = value;
 },
 值:isDarkMode)

第 4 步:添加自定义颜色

它工作正常,因为它会在所有图标和文本中显示相同的颜色。如果我们想在图标上使用不同的颜色,我们必须为主题创建一个扩展。创建一个类并使用 ThemeExtension 进行扩展,并添加您想要自定义的必要字段。

Flutter 主题:具有自定义颜色的浅色和深色主题
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 中添加这个扩展属性,并根据颜色定义主题。

Flutter 主题:具有自定义颜色的浅色和深色主题
扩展:<ThemeExtension<AppColors>>[
 应用颜色(
   color1: isDarkTheme ? 颜色.blue : 颜色.blueGrey,
   color2: isDarkTheme ? 颜色.pink : Colors.pinkAccent,
   color3: isDarkTheme ? Colors.yellow : Colors.limeAccent,
 ),

创建我们用来轻松访问自定义颜色的另一个扩展函数。

Flutter 主题:具有自定义颜色的浅色和深色主题
AppColors 颜色(上下文)=> Theme.of(上下文).extension<AppColors>()!;

我们可以简单地使用colors(context).color1访问小部件中的这些颜色如果我们不指定图标颜色,它将从 listTileTheme 中获取颜色。

Flutter 主题:具有自定义颜色的浅色和深色主题
列表块(
   前导:图标(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 主题:具有自定义颜色的浅色和深色主题
导入“包: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 主题:具有自定义颜色的浅色和深色主题
导入“包: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 教程上找到这些解决方案。

言鼎科技

The End