Flutter 主題:具有自定義顏色的淺色和深色主題
際項(xiàng)目中,我們需要為我們的應(yīng)用程序品牌添加自定義顏色。
在這篇博客中,我們將逐步分享如何創(chuàng)建一個(gè) 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 賦予不同的值。
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。
第 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)用。
類 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)。
轉(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ò)展,并添加您想要自定義的必要字段。
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ù)顏色定義主題。
擴(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ù)。
我們可以簡(jiǎn)單地使用colors(context).color1訪問(wèn)小部件中的這些顏色。如果我們不指定圖標(biāo)顏色,它將從 listTileTheme 中獲取顏色。
列表塊(
前導(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 步:完整源代碼
這是主題類的代碼:
導(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),
);
}}
這是我們主屏幕的代碼:
導(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 教程上找到這些解決方案。
(言鼎科技)