Flutter 主題:具有自定義顏色的淺色和深色主題

言鼎科技 2023-05-25 784

際項(xiàng)目中,我們需要為我們的應(yīng)用程序品牌添加自定義顏色。

在這篇博客中,我們將逐步分享如何創(chuàng)建一個(gè) flutter 自定義主題

Flutter 主題:具有自定義顏色的淺色和深色主題

使用自定義顏色的 Flutter 主題分步指南

要成功實(shí)施 Flutter 主題化,您必須滿足以下先決條件:

  • 創(chuàng)建顫振項(xiàng)目

  • 在 yaml 中添加 riverpod 包(注意:您可以根據(jù)自己的方便使用任何狀態(tài)管理包)

準(zhǔn)備好繼續(xù)操作后,請(qǐng)連續(xù)執(zhí)行以下步驟以啟用自定義 Flutter 主題。

想要實(shí)現(xiàn)自定義選項(xiàng)以在您的應(yīng)用程序中動(dòng)態(tài)更改主題?
聘請(qǐng)Bacancy 的 Flutter 開發(fā)人員為您的應(yīng)用品牌添加或自定義主題顏色

第 1 步:創(chuàng)建淺色/深色主題

為了創(chuàng)建明暗模式的主題,我們使用 ThemeData 類并根據(jù)需要自定義顏色和其他屬性。我們已經(jīng)創(chuàng)建了一種基于選定的淺色/深色主題獲取 ThemeDate 的方法。

我們根據(jù)所選主題為 scaffoldBackgroundColor、bodyColor、thumbColor、listTileTheme 和 appBarTheme 賦予不同的值。

Flutter 主題:具有自定義顏色的淺色和深色主題
ThemeData getAppTheme(BuildContext context, bool isDarkTheme) {
 返回主題數(shù)據(jù)(
   scaffoldBackgroundColor: isDarkTheme ? 顏色.black : 顏色.white,
   文本主題:Theme.of(context)
       .text主題
       .copyWith(
         標(biāo)題?。?br/>              Theme.of(context).textTheme.titleSmall?.copyWith(fontSize: 11),
       )
       。申請(qǐng)(
         bodyColor: isDarkTheme ? 顏色.white : 顏色.black,
         顯示顏色:Colors.grey,
       ),
   切換主題:切換主題數(shù)據(jù)(
     thumbColor: MaterialStateProperty.all(
         是深色主題嗎?顏色.橙色 : 顏色.紫色),
   ),
   listTileTheme: ListTileThemeData(
       iconColor: isDarkTheme ? 顏色.橙色 : 顏色.紫色),
   appBarTheme: AppBarTheme(
       backgroundColor: isDarkTheme ? 顏色.black : 顏色.white,
       圖標(biāo)主題:
           IconThemeData(顏色:isDarkTheme?Colors.white:Colors.black54)),
 );}

第 2 步:使用 River-pod 為主題狀態(tài)創(chuàng)建提供者

我們將使用 river-pod 來(lái)管理應(yīng)用主題狀態(tài)。我們只想存儲(chǔ) bool 值來(lái)管理淺色或深色主題,因此我們將使用 StateProvider。

Flutter 主題:具有自定義顏色的淺色和深色主題
final appThemeProvider = StateProvider<bool>((ref) => false);

第 3 步:在 App 中使用主題

我們?cè)陧?xiàng)目中使用 river-pod,因此我們必須使用 ProviderScope 包裝 MyApp 以訪問(wèn)所有提供程序的 though-out 應(yīng)用程序。MyApp 擴(kuò)展了 ConsumerWidget,因此我們可以在構(gòu)建方法中獲取 WidgetRef 對(duì)象,并使用 ref 變量訪問(wèn)任何 river-pod。getAppTheme(context, ref.watch(appThemeProvider))方法監(jiān)聽?wèi)?yīng)用主題的任何變化并相應(yīng)地更新應(yīng)用。

Flutter 主題:具有自定義顏色的淺色和深色主題
類 MyApp 擴(kuò)展 ConsumerWidget {
 const MyApp({super.key});
 @覆蓋
 小部件構(gòu)建(BuildContext 上下文,WidgetRef ref){
   返回 MaterialApp(
     title: 'Flutter Light/Dark Theme',
     debugShowCheckedModeBanner: false,
     主題:getAppTheme(上下文,ref.watch(appThemeProvider)),
     主頁(yè):const MyHomePage(),
   );
 }}

ref.read(appThemeProvider.notifier).state = value當(dāng)切換狀態(tài)從淺色/深色狀態(tài)更改時(shí),我們正在更新 appThemeProvider 中的主題狀態(tài)。

Flutter 主題:具有自定義顏色的淺色和深色主題
轉(zhuǎn)變(
 activeColor: Colors.orange,
 onChanged:(值){
   ref.read(appThemeProvider.notifier).state = value;
 },
 值:isDarkMode)

第 4 步:添加自定義顏色

它工作正常,因?yàn)樗鼤?huì)在所有圖標(biāo)和文本中顯示相同的顏色。如果我們想在圖標(biāo)上使用不同的顏色,我們必須為主題創(chuàng)建一個(gè)擴(kuò)展。創(chuàng)建一個(gè)類并使用 ThemeExtension 進(jìn)行擴(kuò)展,并添加您想要自定義的必要字段。

Flutter 主題:具有自定義顏色的淺色和深色主題
AppColors 類擴(kuò)展 ThemeExtension<AppColors> {
 最終顏色?顏色1;
 最終顏色?顏色2;
 最終顏色?顏色3;
 常量 AppColors({
   需要this.color1,
   需要this.color2,
   需要this.color3,
 });
 @覆蓋
 AppColors copyWith({
   顏色?顏色1,
   顏色?顏色2,
   顏色?顏色3,
 }) {
   返回 AppColors(
     顏色 1:顏色 1 ?? 這個(gè).color1,
     顏色 2:顏色 2 ?? 這個(gè).color2,
     顏色 3:顏色 3 ?? 這個(gè).color3,
   );
 }
 @覆蓋
 AppColors lerp(ThemeExtension<AppColors>? other, double t) {
   如果(其他是!AppColors){
     歸還這個(gè);
   }
   返回 AppColors(
     color1: Color.lerp(color1, other.color1, t),
     color2: Color.lerp(color2, other.color2, t),
     color3: Color.lerp(color3, other.color3, t),
   );
 }}

現(xiàn)在在我們的創(chuàng)建方法 getAppTheme 中的 ThemeData 中添加這個(gè)擴(kuò)展屬性,并根據(jù)顏色定義主題。

Flutter 主題:具有自定義顏色的淺色和深色主題
擴(kuò)展:<ThemeExtension<AppColors>>[
 應(yīng)用顏色(
   color1: isDarkTheme ? 顏色.blue : 顏色.blueGrey,
   color2: isDarkTheme ? 顏色.pink : Colors.pinkAccent,
   color3: isDarkTheme ? Colors.yellow : Colors.limeAccent,
 ),

創(chuàng)建我們用來(lái)輕松訪問(wèn)自定義顏色的另一個(gè)擴(kuò)展函數(shù)。

Flutter 主題:具有自定義顏色的淺色和深色主題
AppColors 顏色(上下文)=> Theme.of(上下文).extension<AppColors>()!;

我們可以簡(jiǎn)單地使用colors(context).color1訪問(wèn)小部件中的這些顏色。如果我們不指定圖標(biāo)顏色,它將從 listTileTheme 中獲取顏色。

Flutter 主題:具有自定義顏色的淺色和深色主題
列表塊(
   前導(dǎo):圖標(biāo)(Icons.chat_outlined,顏色:顏色(上下文).color3),
   title: Text( "幫助中心", style: Theme.of(context).textTheme.titleSmall),
),列表塊(
   前導(dǎo):const Icon(Icons.notifications),
   title: Text("Notification", style: Theme.of(context).textTheme.titleSmall),),

第 5 步:完整源代碼

這是主題類的代碼:

Flutter 主題:具有自定義顏色的淺色和深色主題
導(dǎo)入“包:flutter/material.dart”;AppColors 顏色(上下文)=> Theme.of(上下文).extension<AppColors>()!;ThemeData getAppTheme(BuildContext context, bool isDarkTheme) {
 返回主題數(shù)據(jù)(
   擴(kuò)展:<ThemeExtension<AppColors>>[
     應(yīng)用顏色(
       color1: isDarkTheme ? 顏色.blue : 顏色.green,
       color2: isDarkTheme ? 顏色.pink : 顏色.blue,
       color3: isDarkTheme ? 顏色.黃色:顏色.紅色,
     ),
   ],
   scaffoldBackgroundColor: isDarkTheme ? 顏色.black : 顏色.white,
   文本主題:Theme.of(context)
       .text主題
       .copyWith(
         標(biāo)題?。?br/>              Theme.of(context).textTheme.titleSmall?.copyWith(fontSize: 12),
       )
       。申請(qǐng)(
         bodyColor: isDarkTheme ? 顏色.white : 顏色.black,
         顯示顏色:Colors.grey,
       ),
   切換主題:切換主題數(shù)據(jù)(
     thumbColor: MaterialStateProperty.all(
         是深色主題嗎?顏色.橙色 : 顏色.紫色),
   ),
   listTileTheme: ListTileThemeData(
       iconColor: isDarkTheme ? 顏色.橙色 : 顏色.紫色),
   appBarTheme: AppBarTheme(
       backgroundColor: isDarkTheme ? 顏色.black : 顏色.white,
       圖標(biāo)主題:
           IconThemeData(顏色:isDarkTheme?Colors.white:Colors.black54)),
 );}@immutableAppColors 類擴(kuò)展 ThemeExtension<AppColors> {
 最終顏色?顏色1;
 最終顏色?顏色2;
 最終顏色?顏色3;
 常量 AppColors({
   需要this.color1,
   需要this.color2,
   需要this.color3,
 });
 @覆蓋
 AppColors copyWith({
   顏色?顏色1,
   顏色?顏色2,
   顏色?顏色3,
 }) {
   返回 AppColors(
     顏色 1:顏色 1 ?? 這個(gè).color1,
     顏色 2:顏色 2 ?? 這個(gè).color2,
     顏色 3:顏色 3 ?? 這個(gè).color3,
   );
 }
 @覆蓋
 AppColors lerp(ThemeExtension<AppColors>? other, double t) {
   如果(其他是!AppColors){
     歸還這個(gè);
   }
   返回 AppColors(
     color1: Color.lerp(color1, other.color1, t),
     color2: Color.lerp(color2, other.color2, t),
     color3: Color.lerp(color3, other.color3, t),
   );
 }}

這是我們主屏幕的代碼:

Flutter 主題:具有自定義顏色的淺色和深色主題
導(dǎo)入“包:flutter/material.dart”;導(dǎo)入“包:flutter_riverpod/flutter_riverpod.dart”;導(dǎo)入“包:light_dark_mode/provider%20/app_theme_provider.dart”;導(dǎo)入“包:light_dark_mode/utils/app_theme.dart”;無(wú)效主要(){
 runApp(const ProviderScope(child: MyApp()));}類 MyApp 擴(kuò)展 ConsumerWidget {
 const MyApp({super.key});
 @覆蓋
 小部件構(gòu)建(BuildContext 上下文,WidgetRef ref){
   返回 MaterialApp(
     title: 'Flutter Light/Dark Theme',
     debugShowCheckedModeBanner: false,
     主題:getAppTheme(上下文,ref.watch(appThemeProvider)),
     主頁(yè):const MyHomePage(),
   );
 }}類 MyHomePage 擴(kuò)展 ConsumerWidget {
 const MyHomePage({Key?key}) : super(key: key);
 @覆蓋
 小部件構(gòu)建(BuildContext 上下文,WidgetRef ref){
   var isDarkMode = ref.watch(appThemeProvider);
   返回腳手架(
     應(yīng)用欄:應(yīng)用欄(
       海拔:0,
       前導(dǎo):const Icon(Icons.arrow_back_ios_sharp),
       動(dòng)作:常量 [
         填充(
           填充:EdgeInsets.symmetric(水平:15.0),
           孩子:圖標(biāo)(Icons.add_circle_outline),
         )
       ],
     ),
     身體:填充(
       填充:const EdgeInsets.symmetric(水平:8.0),
       孩子:列表視圖(
         孩子們: [
           圓形頭像(
             半徑:60,
             背景顏色:Colors.grey,
             孩子:填充(
               padding: const EdgeInsets.all(1), // 邊框半徑
               孩子:ClipRRect(
                   borderRadius: BorderRadius.circular(60),
                   孩子:Image.asset(
                     “資產(chǎn)/ic_profile.jpeg”,
                     適合:BoxFit.fill,
                     寬度:120,
                     身高:120,
                   )),
             ),
           ),
           容器(
             保證金:const EdgeInsets.only(頂部:10,底部:60),
             對(duì)齊方式:Alignment.center,
             孩子:文本(
               “測(cè)試用戶”,
               風(fēng)格:Theme.of(context).textTheme.titleLarge,
             ),
           ),
           列表塊(
             前導(dǎo):圖標(biāo)(isDarkMode ? Icons.brightness_3 : Icons.sunny),
             標(biāo)題:文本(
               是黑暗模式嗎?“深色模式”:“淺色模式”,
               風(fēng)格:Theme.of(context).textTheme.titleSmall,
             ),
             尾隨:消費(fèi)者(建造者:(上下文,參考,孩子){
               返回 Transform.scale(
                 規(guī)模:0.7,
                 孩子:開關(guān)(
                   activeColor: Colors.orange,
                   onChanged:(值){
                     ref.read(appThemeProvider.notifier).state = value;
                   },
                   值:isDarkMode,
                 ),
               );
             }),
           ),
           列表塊(
             領(lǐng)先:圖標(biāo)(Icons.grid_on_sharp,顏色:顏色(上下文)。color1,),
             標(biāo)題:文本(
               “故事”,
               風(fēng)格:Theme.of(context).textTheme.titleSmall,
             ),
           ),
           列表塊(
             領(lǐng)先:圖標(biāo)(圖標(biāo)。設(shè)置,顏色:顏色(上下文)。顏色2),
             title: Text("設(shè)置和隱私",
                 樣式:Theme.of(context).textTheme.titleSmall),
           ),
           列表塊(
             前導(dǎo):圖標(biāo)(Icons.chat_outlined,顏色:顏色(上下文).color3),
             標(biāo)題:文本(
               “幫助中心”,
               風(fēng)格:Theme.of(context).textTheme.titleSmall,
             ),
           ),
           列表塊(
             前導(dǎo):const Icon(Icons.notifications),
             標(biāo)題:文本(
               “通知”,
               風(fēng)格:Theme.of(context).textTheme.titleSmall,
             ),
           ),
         ],
       ),
     ),
   );
 }}

您可以在此處找到完整代碼:GitHub 存儲(chǔ)庫(kù)。

結(jié)論

我希望這篇博客能幫助您定制您的 Flutter 應(yīng)用主題。在這篇博客中,我們?cè)?ThemeExtension 中自定義了 Colors;但是,我們可以使用任何字段來(lái)自定義值。Flutter 主題化只是一方面,我們還提供了其他幾種解決方案,您可以在Flutter 教程上找到這些解決方案。

言鼎科技

The End