
老鐵記得 轉(zhuǎn)發(fā) ,貓哥會呈現(xiàn)更多 Flutter 好文~~~~
微信群 ducafecat
b 站 https://space.bilibili.com/404904528
原文
https://vbacik-10.medium.com/flutter-build-theme-with-abstract-factory-method-e07df8f730e2
代碼
https://github.com/VB10/flutter-abstract-theme-manager
參考
正文
最多的應(yīng)用程序至少創(chuàng)建了一個主題。也許這對于第一個版本來說已經(jīng)足夠了,但是如果這個項目繼續(xù)增長呢?讓我們來看看怎么做。
我們知道項目設(shè)計的主題有多重要,所以我們將為項目創(chuàng)建一個主題管理器。讓我們創(chuàng)建一個主題管理器以及這個購物頁面。

- 設(shè)計稿
https://adobe.ly/xdfreshfooduikit
首先,它需要一個頁面設(shè)計,如也這個頁面可以連接到服務(wù)。(我為這個示例頁面創(chuàng)建了這個端點)
- Background 背景
- App bar - 應(yīng)用程式欄
- Search Bar - 搜尋欄
— Search Icon ー搜尋圖示
— Search Text ー搜尋文字
— Microphone Icon ー麥克風(fēng)圖標(biāo) - ListView
— Product Card ー產(chǎn)品卡 - TabBar
— TabBar Icons ー TabBar 圖標(biāo)集
因此,我們需要一個調(diào)色板使用這個項目。如果你的設(shè)計工具包有一個調(diào)色板,你可以在設(shè)計工具包中得到所有的顏色。

項目必須在需要新小部件時使用這個調(diào)色板。實際上,由于有了主題經(jīng)理,項目會更容易成長。最后,我們準(zhǔn)備好了 Hacking 時間,因此我們將同時使用工廠方法模式和頁面原子設(shè)計。
Hacking Time
首先,我更喜歡先寫核心特性,這就是為什么我們不會在代碼完成時加倍工作的原因:
- 使用不同顏色和樣式的 ITheme 抽象類
- 用于從一個點管理不同主題的 ThemeFactory 類
工廠設(shè)計是創(chuàng)新模式之一。這個模式提供了高級對象,因為客戶機什么都不知道?,F(xiàn)在,該模式創(chuàng)建了一個自定義對象,以便項目可以使用這個方案。

現(xiàn)在我們知道了這個結(jié)構(gòu)需要什么,因為我們可以編寫一個同時包含文本和顏色的界面。這個接口提供了一個中心視點,因此項目需要。讓我們寫下這些要點。
文本主題界面
每個項目都需要這一點,因為大多數(shù)用法都指向項目的文本指南。所以我們創(chuàng)建基本樣式指南后,非常容易從視圖使用。有時我們需要自定義文本樣式并不意味著你不使用當(dāng)前的樣式。我們可以使用 copyWith 函數(shù),這樣就可以像 headline5 一樣使用視圖,也可以添加自定義屬性,如文本顏色。
abstract class ITextTheme {
final Color? primaryColor;
late final TextTheme data;
TextStyle? headline1;
TextStyle? headline3;
TextStyle? headline4;
TextStyle? headline5;
TextStyle? headline6;
TextStyle? subtitle1;
TextStyle? subtitle2;
TextStyle? bodyText1;
TextStyle? bodyText2;
String? fontFamily;
ITextTheme(this.primaryColor);
}
如果您的項目設(shè)計有一個工具包,您可以使用 zeplin 工具。這個工具在樣式指南選項卡中獲取所有的文本樣式。

顏色主題界面
指向項目是非常重要的,因為你知道顏色無處不在。所以我們?nèi)绾喂芾砀嗟捻椖亢苋菀卓刂啤C總€項目都有一個特定的顏色模式,您必須在代碼中使用這個模式。如果你不使用模式和項目有一個靜態(tài)的顏色代碼,你不會添加多主題選項,另外你不能管理顏色問題。
abstract class IColors {
_AppColors get colors;
Color? scaffoldBackgroundColor;
Color? appBarColor;
Color? tabBarColor;
Color? tabbarSelectedColor;
Color? tabbarNormalColor;
Brightness? brightness;
ColorScheme? colorScheme;
}
我說像 paragraph 關(guān)于 zeplin。再次你可以使用這個和你能夠所有的顏色屬性。

Abstract Factory Manager
為多界面創(chuàng)建的管理器。此管理器將為項目創(chuàng)建 ThemeData 實例。由于這個接口,您可以創(chuàng)建一個新的主題實例。這個新的主題只需要一個配色方案等。
abstract class ITheme {
ITextTheme get textTheme;
IColors get colors;
}
是的,它看起來很簡單,對任何項目都很有用。最后,我們準(zhǔn)備使用核心主題繪制操作,因此項目可以聲明這個結(jié)構(gòu)的自定義主題。也許,這些主題接口可以改進得更高級?,F(xiàn)在對于這個項目來說已經(jīng)足夠了。
最后需要工廠創(chuàng)建者和我們使用這個項目的主題管理器
abstract class ThemeManager {
static ThemeData craeteTheme(ITheme theme) => ThemeData(
fontFamily: theme.textTheme.fontFamily,
textTheme: theme.textTheme.data,
cardColor: theme.colors.colorScheme?.onSecondary,
floatingActionButtonTheme: FloatingActionButtonThemeData(
foregroundColor: theme.colors.colors.white,
backgroundColor: theme.colors.colors.green),
appBarTheme: AppBarTheme(backgroundColor: theme.colors.appBarColor),
scaffoldBackgroundColor: theme.colors.scaffoldBackgroundColor,
colorScheme: theme.colors.colorScheme);
}
我計劃只有具體的領(lǐng)域,因為它的項目只有兩個頁面,因為你知道這個樣本。你必須創(chuàng)建文本樣式和配色方案區(qū)域的其他區(qū)域。讓我們用這個結(jié)構(gòu)創(chuàng)建自定義主題,我們將展示這種使用優(yōu)勢。
Ligh Theme on Project
實際上,我們有一個結(jié)構(gòu)和項目,如何創(chuàng)建一個輕的主題。
class AppThemeLight extends ITheme {
@override
late final ITextTheme textTheme;
AppThemeLight() {
textTheme = TextThemeLight(colors.colors.mediumGrey);
}
@override
IColors get colors => LightColors();
}
當(dāng)然,暗主題創(chuàng)建這樣,因此只是改變風(fēng)格的指導(dǎo)方針和項目可以直接使用。您可以在這里訪問黑暗主題代碼。
TextTheme Light 需要繪制文本默認(rèn)顏色的基本顏色,而淺色已經(jīng)從 zeplin 樣式創(chuàng)建。
class TextThemeLight implements ITextTheme {
@override
late final TextTheme data;
@override
TextStyle? bodyText1;
@override
TextStyle? bodyText2;
@override
TextStyle? headline1;
@override
TextStyle? headline3;
@override
TextStyle? headline4;
@override
TextStyle? headline5;
@override
TextStyle? headline6;
@override
TextStyle? subtitle1;
@override
TextStyle? subtitle2;
final Color? primaryColor;
TextThemeLight(this.primaryColor) {
data = TextTheme(
headline6: TextStyle(fontSize: 20, fontWeight: FontWeight.normal),
subtitle1: TextStyle(fontSize: 16.0),
).apply(bodyColor: primaryColor);
fontFamily = GoogleFonts.arvo().fontFamily;
}
@override
String? fontFamily;
}
好的,如果我們想看淺色的主題實例,它顯示了這一點。
class LightColors implements IColors {
@override
final _AppColors colors = _AppColors();
@override
ColorScheme? colorScheme;
@override
Color? appBarColor;
@override
Color? scaffoldBackgroundColor;
@override
Color? tabBarColor;
@override
Color? tabbarNormalColor;
@override
Color? tabbarSelectedColor;
LightColors() {
appBarColor = colors.white;
scaffoldBackgroundColor = colors.white;
tabBarColor = colors.green;
tabbarNormalColor = colors.lighterGrey;
tabbarSelectedColor = colors.darkerGrey;
colorScheme = ColorScheme.light()
.copyWith(onPrimary: colors.green, onSecondary: colors.white);
brightness = Brightness.light;
}
@override
Brightness? brightness;
}
有時需要準(zhǔn)備風(fēng)格,因為沒有足夠的風(fēng)格知識。這時你可以為你的項目使用一個配色方案實例,這樣你就可以得到材質(zhì)配色方案,因此可以添加你自定義的業(yè)務(wù)層。
而 Light 主題就是準(zhǔn)備使用的。該項目只需要主題工廠方法,您可以編寫這個類實例。對于項目顏色的所有內(nèi)容,這都是可以接受的。
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: '@VB10',
theme: ThemeManager.craeteTheme(AppThemeLight()),
home: SampleView(),
);
}
}
是的,我們可以開始在搜索結(jié)果屏幕上繪圖。特別是不要忘記這個方法,讓我們看看如何為這個項目創(chuàng)建一個主題實例。
abstract class ThemeManager {
static ThemeData craeteTheme(ITheme theme) => ThemeData(
fontFamily: theme.textTheme.fontFamily,
textTheme: theme.textTheme.data,
cardColor: theme.colors.colorScheme?.onSecondary,
tabBarTheme: TabBarTheme(
indicator: BoxDecoration(),
labelColor: theme.colors.tabbarSelectedColor,
unselectedLabelColor: theme.colors.tabbarNormalColor,
),
floatingActionButtonTheme: FloatingActionButtonThemeData(
foregroundColor: theme.colors.colors.white,
backgroundColor: theme.colors.colors.green),
appBarTheme: AppBarTheme(backgroundColor: theme.colors.appBarColor),
scaffoldBackgroundColor: theme.colors.scaffoldBackgroundColor,
colorScheme: theme.colors.colorScheme);
}
現(xiàn)在項目直接依賴于所有的主題實例,因為我們只是改變主題值后,這個項目去一個新的配色方案,另外項目從來不需要任何代碼的設(shè)計時間。這一點意味著你的項目設(shè)計已經(jīng)完成了所有的工作
Feature Page
我們有一個主題實例,所以只需調(diào)用這個實例,一切就緒。首先,繪制頁面樹非常重要,更好地理解。
[圖片上傳失敗...(image-a4213-1625618584460)]
現(xiàn)在編碼非常簡單,因為我們知道如何繪制這個。特別是您對編碼時間非常注意,因此可以在頁面設(shè)計中始終使用主題實例。該項目有一個主題設(shè)計,因為可以直接調(diào)用這個變量。例如,任何頁面可以需要背景色,所以我們不需要一遍又一遍地寫,因為我們有使用這種情況的主題實例。
[圖片上傳失敗...(image-361204-1625618584460)]
是的,我們準(zhǔn)備開發(fā)另外的主題管理器和小部件樹結(jié)構(gòu)。首先,讓我們在編碼中創(chuàng)建一個 tab 視圖結(jié)構(gòu)。
final List<MapEntry<Widget, IconData>> _pages = [
MapEntry(SampleView(), Icons.search),
MapEntry(Container(), Icons.search),
MapEntry(Container(), Icons.search),
MapEntry(Container(), Icons.search),
];
@override
Widget build(BuildContext context) {
return DefaultTabController(
length: _pages.length,
child: Scaffold(
floatingActionButtonLocation:
FloatingActionButtonLocation.centerDocked,
floatingActionButton: floatingActionButton(context),
bottomNavigationBar: _bottomAppBar(),
body: TabBarView(children: _pages.map((e) => e.key).toList()),
));
}
實際上,我們看到了 fab 按鈕,我們需要一個自定義顏色,因為這個顏色是為藍(lán)色創(chuàng)建的,但是我們在主題中添加了這個自定義代碼,只寫了一個浮動的操作按鈕。此按鈕從上下文中讀取主題實例中的 own 屬性。
[圖片上傳失敗...(image-837c1f-1625618584460)]
我說你不需要額外的代碼,直接調(diào)用這個小部件。
FloatingActionButton floatingActionButton(BuildContext context) {
return FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {},
);
}
之后,讓我們顯示搜索結(jié)果頁面設(shè)計。我們談到了這篇頁面設(shè)計對文章的打擊。這對顫振計劃非常重要。你需要一直考慮這個樹型結(jié)構(gòu)。你可以用這個小部件樹的思想做一個很棒的頁面。
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: buildAppBar(context),
body: Padding(
padding: EdgeInsets.only(top: MediaQuery.of(context).size.width * 0.08),
child: Column(
children: [
textFieldSearchCard(context),
Expanded(child: buildGridViewBody()),
],
),
),
);
}
這說明了很多問題。讓我們來看一些小部件,以了解如何使用主題。我們的設(shè)計有一個自定義搜索欄,帶有搜索圖標(biāo)和麥克風(fēng)按鈕。
Widget textFieldSearch(BuildContext context) {
return TextField(
decoration: InputDecoration(
border: InputBorder.none,
prefixIcon: Icon(Icons.search_sharp,
color: Theme.of(context).colorScheme.onPrimary.withOpacity(0.5)),
suffixIconConstraints: BoxConstraints(maxHeight: 30),
suffixIcon: FloatingActionButton(
onPressed: () {},
mini: true,
child: Icon(Icons.mic_sharp),
)),
);
}
這種代碼設(shè)計不需要額外的代碼。您可以從主題上下文中使用這里需要的內(nèi)容。讓我們來看看文本樣式示例:
Text buildTextSub(BuildContext context) {
return Text(
items.searchResults,
style:Theme.of(context).textTheme.headline6?.copyWith(
letterSpacing: -0.2,
fontWeight: FontWeight.w400,
),
);
}
你可以看到這是一個非常簡單和易于管理的代碼,我只是添加了一些自定義代碼并完成了所有的工作。
你可以看到條目屬性,也許這和注釋有重要的關(guān)系。如果您擁有所有的常量值類,并且只想創(chuàng)建常量值,那么您可以在類獲得安全能力之后添加@immutable 注釋。
@immutable
class AppTextItems {
final String searchResults = 'Search Results';
final String brocoliText = 'Broccoli';
}
是的,這個項目可能是理解這個體系結(jié)構(gòu)的一個樣本,但是總是應(yīng)該編寫強大的代碼。
Yees 項目已經(jīng)完成。如果你想改變一個主題,比如黑暗,我們只需要把這個實例改成黑暗,然后就可以了。
[圖片上傳失敗...(image-5f4c53-1625618584460)]
因此,我們采用了抽象的工廠設(shè)計能力和可管理的代碼設(shè)計。它聽起來很適合開發(fā)力量,因為顫振可以改善模式和特殊的角度。

完成了?,F(xiàn)在我們可以直接實施我們自己的項目并管理一切。另一方面,這個項目不需要如何創(chuàng)建新的主題知識,因為你知道我們創(chuàng)建接口。不同的主題剛好適合這些界面,然后一切都完成了。
實際上,本文的主要目標(biāo)是如何在主題實例中使用這種模式,因此這方面的知識對您的開發(fā)生活非常重要。
感謝你閱讀《感謝你閱讀《為你的生命健康》》
https://github.com/VB10/flutter-abstract-theme-manager
? 貓哥
往期
開源
GetX Quick Start
https://github.com/ducafecat/getx_quick_start
新聞客戶端
https://github.com/ducafecat/flutter_learn_news
strapi 手冊譯文
微信討論群 ducafecat
系列集合
譯文
https://ducafecat.tech/categories/%E8%AF%91%E6%96%87/
開源項目
https://ducafecat.tech/categories/%E5%BC%80%E6%BA%90/
Dart 編程語言基礎(chǔ)
https://space.bilibili.com/404904528/channel/detail?cid=111585
Flutter 零基礎(chǔ)入門
https://space.bilibili.com/404904528/channel/detail?cid=123470
Flutter 實戰(zhàn)從零開始 新聞客戶端
https://space.bilibili.com/404904528/channel/detail?cid=106755
Flutter 組件開發(fā)
https://space.bilibili.com/404904528/channel/detail?cid=144262
Flutter Bloc
https://space.bilibili.com/404904528/channel/detail?cid=177519
Flutter Getx4
https://space.bilibili.com/404904528/channel/detail?cid=177514
Docker Yapi
https://space.bilibili.com/404904528/channel/detail?cid=130578