关于flutter:用抽象工厂方法构建-Flutter-主题

44次阅读

共计 8404 个字符,预计需要花费 22 分钟才能阅读完成。

老铁记得 转发,猫哥会出现更多 Flutter 好文~~~~

微信群 ducafecat

b 站 https://space.bilibili.com/40…

原文

https://vbacik-10.medium.com/…

代码

https://github.com/VB10/flutt…

参考

  • https://zeplin.io

注释

最多的应用程序至多创立了一个主题。兴许这对于第一个版本来说曾经足够了,然而如果这个我的项目持续增长呢?让咱们来看看怎么做。

咱们晓得我的项目设计的主题有多重要,所以咱们将为我的项目创立一个主题管理器。让咱们创立一个主题管理器以及这个购物页面。

  • 设计稿
    https://adobe.ly/xdfreshfoodu…

首先,它须要一个页面设计,如也这个页面能够连贯到服务。(我为这个示例页面创立了这个端点)

  • 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 工具。这个工具在款式指南选项卡中获取所有的文本款式。

https://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 我的项目曾经实现。如果你想扭转一个主题,比方光明,咱们只须要把这个实例改成光明,而后就能够了。

因而,咱们采纳了形象的工厂设计能力和可治理的代码设计。它听起来很适宜开发力量,因为颤振能够改善模式和非凡的角度。

实现了。当初咱们能够间接施行咱们本人的我的项目并治理所有。另一方面,这个我的项目不须要如何创立新的主题常识,因为你晓得咱们创立接口。不同的主题刚好适宜这些界面,而后所有都实现了。

实际上,本文的次要指标是如何在主题实例中应用这种模式,因而这方面的常识对您的开发生存十分重要。

感激你浏览《感激你浏览《为你的生命衰弱》》

https://github.com/VB10/flutt…


© 猫哥

https://ducafecat.tech/

https://github.com/ducafecat

往期

开源

GetX Quick Start

https://github.com/ducafecat/…

新闻客户端

https://github.com/ducafecat/…

strapi 手册译文

https://getstrapi.cn

微信探讨群 ducafecat

系列汇合

译文

https://ducafecat.tech/catego…

开源我的项目

https://ducafecat.tech/catego…

Dart 编程语言根底

https://space.bilibili.com/40…

Flutter 零根底入门

https://space.bilibili.com/40…

Flutter 实战从零开始 新闻客户端

https://space.bilibili.com/40…

Flutter 组件开发

https://space.bilibili.com/40…

Flutter Bloc

https://space.bilibili.com/40…

Flutter Getx4

https://space.bilibili.com/40…

Docker Yapi

https://space.bilibili.com/40…

正文完
 0