用抽象工廠方法構建 Flutter 主題

會煮咖啡的貓發表於2021-07-07

老鐵記得 轉發 ,貓哥會呈現更多 Flutter 好文~~~~

微信群 ducafecat

b 站 space.bilibili.com/404904528

原文

vbacik-10.medium.com/flutter-bui…

程式碼

github.com/VB10/flutte…

參考

正文

最多的應用程式至少建立了一個主題。也許這對於第一個版本來說已經足夠了,但是如果這個專案繼續增長呢?讓我們來看看怎麼做。

我們知道專案設計的主題有多重要,所以我們將為專案建立一個主題管理器。讓我們建立一個主題管理器以及這個購物頁面。

首先,它需要一個頁面設計,如也這個頁面可以連線到服務。(我為這個示例頁面建立了這個端點)

  • Background 背景
  • App bar - 應用程式欄
  • Search Bar - 搜尋欄 — Search Icon ー搜尋圖示 — Search Text ー搜尋文字 — Microphone Icon ー麥克風圖示
  • ListView — Product Card ー產品卡
  • TabBar — TabBar Icons ー TabBar 圖示集

因此,我們需要一個調色盤使用這個專案。如果你的設計工具包有一個調色盤,你可以在設計工具包中得到所有的顏色。

專案必須在需要新小部件時使用這個調色盤。實際上,由於有了主題經理,專案會更容易成長。最後,我們準備好了 Hacking 時間,因此我們將同時使用工廠方法模式和頁面原子設計。

Hacking Time

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

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

工廠設計是創新模式之一。這個模式提供了高階物件,因為客戶機什麼都不知道。現在,該模式建立了一個自定義物件,以便專案可以使用這個方案。

現在我們知道了這個結構需要什麼,因為我們可以編寫一個同時包含文字和顏色的介面。這個介面提供了一箇中心視點,因此專案需要。讓我們寫下這些要點。

文字主題介面

每個專案都需要這一點,因為大多數用法都指向專案的文字指南。所以我們建立基本樣式指南後,非常容易從檢視使用。有時我們需要自定義文字樣式並不意味著你不使用當前的樣式。我們可以使用 copyWith 函式,這樣就可以像 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);
}
複製程式碼

如果您的專案設計有一個工具包,您可以使用 zeplin 工具。這個工具在樣式指南選項卡中獲取所有的文字樣式。

zeplin.io/

顏色主題介面

指向專案是非常重要的,因為你知道顏色無處不在。所以我們如何管理更多的專案很容易控制。每個專案都有一個特定的顏色模式,您必須在程式碼中使用這個模式。如果你不使用模式和專案有一個靜態的顏色程式碼,你不會新增多主題選項,另外你不能管理顏色問題。

abstract class IColors {
  _AppColors get colors;
  Color? scaffoldBackgroundColor;
  Color? appBarColor;
  Color? tabBarColor;
  Color? tabbarSelectedColor;
  Color? tabbarNormalColor;
  Brightness? brightness;

  ColorScheme? colorScheme;
}
複製程式碼

我說像 paragraph 關於 zeplin。再次你可以使用這個和你能夠所有的顏色屬性。

Abstract Factory Manager

為多介面建立的管理器。此管理器將為專案建立 ThemeData 例項。由於這個介面,您可以建立一個新的主題例項。這個新的主題只需要一個配色方案等。

abstract class ITheme {
  ITextTheme get textTheme;
  IColors get colors;
}
複製程式碼

是的,它看起來很簡單,對任何專案都很有用。最後,我們準備使用核心主題繪製操作,因此專案可以宣告這個結構的自定義主題。也許,這些主題介面可以改進得更高階。現在對於這個專案來說已經足夠了。

最後需要工廠建立者和我們使用這個專案的主題管理器

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);
}
複製程式碼

我計劃只有具體的領域,因為它的專案只有兩個頁面,因為你知道這個樣本。你必須建立文字樣式和配色方案區域的其他區域。讓我們用這個結構建立自定義主題,我們將展示這種使用優勢。

Ligh Theme on Project

實際上,我們有一個結構和專案,如何建立一個輕的主題。

class AppThemeLight extends ITheme {
  @override
  late final ITextTheme textTheme;

  AppThemeLight() {
    textTheme = TextThemeLight(colors.colors.mediumGrey);
  }

  @override
  IColors get colors => LightColors();
}
複製程式碼

當然,暗主題建立這樣,因此只是改變風格的指導方針和專案可以直接使用。您可以在這裡訪問黑暗主題程式碼。

TextTheme Light 需要繪製文字預設顏色的基本顏色,而淺色已經從 zeplin 樣式建立。

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;
}
複製程式碼

有時需要準備風格,因為沒有足夠的風格知識。這時你可以為你的專案使用一個配色方案例項,這樣你就可以得到材質配色方案,因此可以新增你自定義的業務層。

而 Light 主題就是準備使用的。該專案只需要主題工廠方法,您可以編寫這個類例項。對於專案顏色的所有內容,這都是可以接受的。

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '@VB10',
      theme: ThemeManager.craeteTheme(AppThemeLight()),
      home: SampleView(),
    );
  }
}
複製程式碼

是的,我們可以開始在搜尋結果螢幕上繪圖。特別是不要忘記這個方法,讓我們看看如何為這個專案建立一個主題例項。

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);
}
複製程式碼

現在專案直接依賴於所有的主題例項,因為我們只是改變主題值後,這個專案去一個新的配色方案,另外專案從來不需要任何程式碼的設計時間。這一點意味著你的專案設計已經完成了所有的工作

Feature Page

我們有一個主題例項,所以只需呼叫這個例項,一切就緒。首先,繪製頁面樹非常重要,更好地理解。

現在編碼非常簡單,因為我們知道如何繪製這個。特別是您對編碼時間非常注意,因此可以在頁面設計中始終使用主題例項。該專案有一個主題設計,因為可以直接呼叫這個變數。例如,任何頁面可以需要背景色,所以我們不需要一遍又一遍地寫,因為我們有使用這種情況的主題例項。

是的,我們準備開發另外的主題管理器和小部件樹結構。首先,讓我們在編碼中建立一個 tab 檢視結構。

  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 按鈕,我們需要一個自定義顏色,因為這個顏色是為藍色建立的,但是我們在主題中新增了這個自定義程式碼,只寫了一個浮動的操作按鈕。此按鈕從上下文中讀取主題例項中的 own 屬性。

我說你不需要額外的程式碼,直接呼叫這個小部件。

FloatingActionButton floatingActionButton(BuildContext context) {
  return FloatingActionButton(
    child: Icon(Icons.add),
    onPressed: () {},
  );
}
複製程式碼

之後,讓我們顯示搜尋結果頁面設計。我們談到了這篇頁面設計對文章的打擊。這對顫振計劃非常重要。你需要一直考慮這個樹型結構。你可以用這個小部件樹的思想做一個很棒的頁面。

  @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()),
          ],
        ),
      ),
    );
  }
複製程式碼

這說明了很多問題。讓我們來看一些小部件,以瞭解如何使用主題。我們的設計有一個自定義搜尋欄,帶有搜尋圖示和麥克風按鈕。

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),
)),
);
}
複製程式碼

這種程式碼設計不需要額外的程式碼。您可以從主題上下文中使用這裡需要的內容。讓我們來看看文字樣式示例:

Text buildTextSub(BuildContext context) {
  return Text(
    items.searchResults,
    style:Theme.of(context).textTheme.headline6?.copyWith(
      letterSpacing: -0.2,
      fontWeight: FontWeight.w400,
      ),
  );
}
複製程式碼

你可以看到這是一個非常簡單和易於管理的程式碼,我只是新增了一些自定義程式碼並完成了所有的工作。

你可以看到條目屬性,也許這和註釋有重要的關係。如果您擁有所有的常量值類,並且只想建立常量值,那麼您可以在類獲得安全能力之後新增@immutable 註釋。

@immutable
class AppTextItems {
  final String searchResults = 'Search Results';
  final String brocoliText = 'Broccoli';
}
複製程式碼

是的,這個專案可能是理解這個體系結構的一個樣本,但是總是應該編寫強大的程式碼。

Yees 專案已經完成。如果你想改變一個主題,比如黑暗,我們只需要把這個例項改成黑暗,然後就可以了。

因此,我們採用了抽象的工廠設計能力和可管理的程式碼設計。它聽起來很適合開發力量,因為顫振可以改善模式和特殊的角度。

完成了。現在我們可以直接實施我們自己的專案並管理一切。另一方面,這個專案不需要如何建立新的主題知識,因為你知道我們建立介面。不同的主題剛好適合這些介面,然後一切都完成了。

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

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

github.com/VB10/flutte…


© 貓哥

ducafecat.tech/

github.com/ducafecat

往期

開源

GetX Quick Start

github.com/ducafecat/g…

新聞客戶端

github.com/ducafecat/f…

strapi 手冊譯文

getstrapi.cn

微信討論群 ducafecat

系列集合

譯文

ducafecat.tech/categories/…

開源專案

ducafecat.tech/categories/…

Dart 程式語言基礎

space.bilibili.com/404904528/c…

Flutter 零基礎入門

space.bilibili.com/404904528/c…

Flutter 實戰從零開始 新聞客戶端

space.bilibili.com/404904528/c…

Flutter 元件開發

space.bilibili.com/404904528/c…

Flutter Bloc

space.bilibili.com/404904528/c…

Flutter Getx4

space.bilibili.com/404904528/c…

Docker Yapi

space.bilibili.com/404904528/c…

相關文章