用抽象工廠方法構(gòu)建 Flutter 主題

image

老鐵記得 轉(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)建一個主題管理器以及這個購物頁面。

image

首先,它需要一個頁面設(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è)計工具包中得到所有的顏色。

image

項目必須在需要新小部件時使用這個調(diào)色板。實際上,由于有了主題經(jīng)理,項目會更容易成長。最后,我們準(zhǔn)備好了 Hacking 時間,因此我們將同時使用工廠方法模式和頁面原子設(shè)計。

Hacking Time

首先,我更喜歡先寫核心特性,這就是為什么我們不會在代碼完成時加倍工作的原因:

  • 使用不同顏色和樣式的 ITheme 抽象類
  • 用于從一個點管理不同主題的 ThemeFactory 類

工廠設(shè)計是創(chuàng)新模式之一。這個模式提供了高級對象,因為客戶機什么都不知道?,F(xiàn)在,該模式創(chuàng)建了一個自定義對象,以便項目可以使用這個方案。

image

現(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 工具。這個工具在樣式指南選項卡中獲取所有的文本樣式。

https://zeplin.io/

image

顏色主題界面

指向項目是非常重要的,因為你知道顏色無處不在。所以我們?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。再次你可以使用這個和你能夠所有的顏色屬性。

image

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ā)力量,因為顫振可以改善模式和特殊的角度。

image

完成了?,F(xiàn)在我們可以直接實施我們自己的項目并管理一切。另一方面,這個項目不需要如何創(chuàng)建新的主題知識,因為你知道我們創(chuàng)建接口。不同的主題剛好適合這些界面,然后一切都完成了。

實際上,本文的主要目標(biāo)是如何在主題實例中使用這種模式,因此這方面的知識對您的開發(fā)生活非常重要。

感謝你閱讀《感謝你閱讀《為你的生命健康》》

https://github.com/VB10/flutter-abstract-theme-manager


? 貓哥

https://ducafecat.tech/

https://github.com/ducafecat

往期

開源

GetX Quick Start

https://github.com/ducafecat/getx_quick_start

新聞客戶端

https://github.com/ducafecat/flutter_learn_news

strapi 手冊譯文

https://getstrapi.cn

微信討論群 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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容