Old iron remember to forward, Brother Mao will present more Flutter good articles~~~~

WeChat group ducafecat

b Station https://space.bilibili.com/404904528

original

https://vbacik-10.medium.com/flutter-build-theme-with-abstract-factory-method-e07df8f730e2

Code

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

reference

text

The most applications have created at least one theme. Maybe this is enough for the first version, but what if the project continues to grow? Let's see how to do it.

We know how important the theme of the project design is, so we will create a theme manager for the project. Let's create a theme manager and this shopping page.

First, it needs a page design, such as this page can be connected to the service. (I created this endpoint for this sample page)

  • Background
  • App bar-App bar
  • Search Bar-Search Bar
    — Search Icon ーSearch Icon
    — Search Text ーSearch text
    — Microphone Icon ーMicrophone Icon
  • ListView
    — Product Card ーProduct Card
  • TabBar
    — TabBar Icons ーTabBar Icon Set

Therefore, we need a palette to use this project. If your design kit has a color palette, you can get all the colors in the design kit.

The project must use this palette when new widgets are needed. In fact, because of the theme manager, the project will be easier to grow. Finally, we are ready for Hacking time, so we will use the factory method pattern and page atomic design at the same time.

Hacking Time

First of all, I prefer to write the core features first, which is why we do not double the work when the code is completed:

  • ITheme abstract class using different colors and styles
  • ThemeFactory class for managing different themes from one point

Factory design is one of the innovative modes. This mode provides high-level objects because the client knows nothing. Now, the pattern creates a custom object so that the project can use this scheme.

Now we know what this structure requires, because we can write an interface that contains both text and color. This interface provides a central point of view, so the project needs it. Let us write down these points.

Text theme interface

Every project needs this because most usage points to the project’s textual guidelines. So after we create the basic style guide, it is very easy to use from the view. Sometimes we need to customize the text style does not mean that you do not use the current style. We can use the copyWith function, so that we can use the view like headline5, and we can also add custom attributes, such as text color.

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);
}

If your project design has a toolkit, you can use the zeplin tool. This tool gets all the text styles in the style guide tab.

https://zeplin.io/

Color theme interface

Pointing to items is very important, because you know that colors are everywhere. So how we manage more projects is easy to control. Each item has a specific color mode, and you must use this mode in your code. If you don't use the mode and the project has a static color code, you won't add multiple theme options, and you can't manage color issues.

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

  ColorScheme? colorScheme;
}

I said like a paragraph about zeplin. Again you can use this and all the color attributes you can.

Abstract Factory Manager

A manager created for multiple interfaces. This manager will create an instance of ThemeData for the project. Thanks to this interface, you can create a new theme instance. This new theme only needs a color scheme and so on.

abstract class ITheme {
  ITextTheme get textTheme;
  IColors get colors;
}

Yes, it looks very simple and very useful for any project. Finally, we are ready to use the core theme drawing operation, so the project can declare a custom theme of this structure. Perhaps, these theme interfaces can be improved to be more advanced. Now it is enough for this project.

Finally, the factory creator and the theme manager we use for this project are needed

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);
}

I plan to only have specific fields, because its project has only two pages, because you know this sample. You have to create text styles and other areas of the color scheme area. Let's create a custom theme with this structure, and we will show the advantages of this usage.

Ligh Theme on Project

Actually, we have a structure and project how to create a light theme.

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

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

  @override
  IColors get colors => LightColors();
}
Of course, the dark theme is created like this, so just the guidelines and items for changing the style can be used directly. You can access the dark theme code here.

TextTheme Light needs to draw the basic color of the default color of the text, and the light color has been created from the zeplin style.

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;
}

Okay, if we want to see light theme examples, it shows this.

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;
}

Sometimes it is necessary to prepare style, because there is not enough style knowledge. At this time, you can use a color scheme example for your project, so you can get the material color scheme, so you can add your custom business layer.

The Light theme is ready to use. The project only needs the theme factory method, and you can write an instance of this class. This is acceptable for all content of the project color.

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

Yes, we can start drawing on the search results screen. Especially don't forget this method, let's see how to create a theme example for this project.

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);
}

Now the project directly depends on all the theme instances, because we just change the theme value, and the project goes to a new color scheme. In addition, the project never requires any code design time. This means that your project design has completed all the work

Feature Page

We have a theme instance, so just call this instance and everything is ready. First of all, drawing the page tree is very important to understand better.

Now coding is very simple, because we know how to draw this. In particular, you pay great attention to coding time, so you can always use theme examples in your page design. The project has a theme design, because this variable can be called directly. For example, any page can require a background color, so we don't need to write it over and over again, because we have examples of themes that use this situation.

Yes, we are going to develop another theme manager and widget tree structure. First, let's create a tab view structure in coding.

  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()),
        ));
  }

In fact, we saw the fab button and we need a custom color because this color was created for blue, but we added this custom code to the theme and only wrote a floating action button. This button reads the own attribute in the theme instance from the context.

I said that you don't need additional code, just call this widget directly.

FloatingActionButton floatingActionButton(BuildContext context) {
  return FloatingActionButton(
    child: Icon(Icons.add),
    onPressed: () {},
  );
}

After that, let us display the search results page design. We talked about the impact of this page design on the article. This is very important for flutter planning. You need to think about this tree structure all the time. You can use the idea of this widget tree to make a great page.

  @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()),
          ],
        ),
      ),
    );
  }

This illustrates a lot of problems. Let's take a look at some widgets to understand how to use themes. Our design has a custom search bar with search icon and microphone button.

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),
)),
);
}

This code design does not require additional code. You can use what you need here from the context of the theme. Let's take a look at an example of text style:

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

You can see that this is a very simple and manageable code, I just added some custom code and completed all the work.

You can see the item properties, maybe this has an important relationship with the comment. If you have all the constant value classes and only want to create constant values, then you can add the @immutable annotation after the class has gained security capabilities.

@immutable
class AppTextItems {
  final String searchResults = 'Search Results';
  final String brocoliText = 'Broccoli';
}

Yes, this project may be a sample for understanding this architecture, but strong code should always be written.

The Yees project has been completed. If you want to change a theme, such as darkness, we just need to change this instance to darkness, and that's it.

Therefore, we have adopted abstract factory design capabilities and manageable code design. It sounds great for developing power, because chatter can improve patterns and special angles.

finished. Now we can directly implement our own projects and manage everything. On the other hand, this project does not require knowledge of how to create new topics, because you know that we create interfaces. Different themes fit these interfaces, and then everything is done.

In fact, the main goal of this article is how to use this pattern in the theme examples, so this knowledge is very important to your development life.

Thank you for reading "Thank you for reading "For Your Life and Health""

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


© Cat brother

https://ducafecat.tech/

https://github.com/ducafecat

Past

Open source

GetX Quick Start

https://github.com/ducafecat/getx_quick_start

News client

https://github.com/ducafecat/flutter_learn_news

strapi manual translation

https://getstrapi.cn

WeChat discussion group ducafecat

Series collection

Translation

https://ducafecat.tech/categories/%E8%AF%91%E6%96%87/

Open source project

https://ducafecat.tech/categories/%E5%BC%80%E6%BA%90/

Dart programming language basics

https://space.bilibili.com/404904528/channel/detail?cid=111585

Getting started with Flutter zero foundation

https://space.bilibili.com/404904528/channel/detail?cid=123470

Flutter actual combat from scratch news client

https://space.bilibili.com/404904528/channel/detail?cid=106755

Flutter component development

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


独立开发者_猫哥
669 声望128 粉丝