design_language 0.0.3 copy "design_language: ^0.0.3" to clipboard
design_language: ^0.0.3 copied to clipboard

discontinued

A package that makes cross-design-language development a breeze.

Welcome to design_language, a package that makes cross-design-language development a breeze.

Motivation #

Standard Flutter does not currently offer a straightforward approach for testing widgets that are targeted to other platforms. Usually developers use Platform.isIOS, Platform.isAndroid, ... to dispatch widgets. For example, let's say the widget tree on iOS should mainly consists of Cupertino widgets and on Android of Material widgets, while on macOS it should render widgets from macos_ui and on Windows those from fluent_ui. One would need 4 different machines to correctly test the UI.

However, what if you don't have an iOS device or a Mac? Or what if constantly switching between physical devices ends up being very time consuming and/or annoying? Wouldn't you prefer to to test all these different layouts directly from your main development station? Since all platforms can render widgets from any design language — e.g., Cupertino widgets can be rendered on any platform — why not take full advantage of that?

This package was made to cover all the scenarios above: by introducing a DesignLanguageNotifier, whose state can be changed at runtime, we can force all widgets build with DesignLanguageDispatcher to be rebuilt.

The package was inspired by flutter_platform_widgets, which comes with a set of ready-to-use, cross-design-language widgets (such as PlatformAlertDialog, PlatformScaffold, ...), which is is a good starting point for learning how to build cross-design-language widgets. However, there are some limitation: for example, PlatformScaffold does not support the Material You variant. You would have to build it yourself anyway with PlatformWidget. This package — design_language — does not come with any prebuilt cross-design-platform widgets: it is up to the developers to determine the exact widget, per design language; this allows for different design-language combinations, and, in general, for greater flexibility (e.g. choosing NavigationBar over BottomNavigationBar).

Getting started #

You need to add design_language to your dependencies.

dependencies:
  design_language: ^latest # replace latest with version number

Usage #

This package aims to become the go-to package for multi-design-language support.

Currently, the following groups are supported:

  • Material and Cupertino
  • Material, Cupertino and Macos
  • Material, Cupertino, Macos and Fluent

In case a different design language group is needed (e.g. only Cupertino and Fluent), either open an issue or fork this repo and create a merge request.

Once you know which group to choose, go to the next step.

Library creation #

After installing the design_language package, there is one more step you need to do before being able to use the utils: exporting the correct "hidden" library.

Create a file inside your lib directory where global configs are done, e.g., lib/core/design/design_language.dart. Open it, and paste one of:

  • Material and Cupertino

    library design_language;
    export 'package:design_language/src/material_cupertino/library.dart';
    
  • Material, Cupertino and Macos

    library design_language;
    export 'package:design_language/src/material_cupertino_macos/library.dart';
    
  • Material, Cupertino, Macos and Fluent

    library design_language;
    export 'package:design_language/src/material_cupertino_macos_fluent/library.dart';
    

Now the library is visible and all the necessary utils are available.

The next steps assume that the selected design language group is Material, Cupertino and Macos.

NB: If you wonder why this library creation approach was taken, consult this file.

DesignLanguage and DesignLanguageNotifier #

You need to instantiate DesignLanguage.notifier before you can use DesignLanguageNotifier or matchDesignLanguage (which are explained later). A good place would be inside your main function.

void main() {
  DesignLanguage.notifier =
      DesignLanguageNotifier(DesignLanguage.fromPhysicalPlatform);
  // the design language is reset upon every restart
  runApp(DesignLanguageDispatcher(
    material: (_, __) => const MyApp(), // selected by default by all platforms but iOS and macOS
    cupertino: (_, __) => const MyIosApp(), // selected by default by iOS
    macos: (_, __) => const MyMacosApp(), // selected by default by macOS
  ));
}

If the goal is to force a specific design language on startup for all platforms:

void main() {
  DesignLanguage.notifier =
      DesignLanguageNotifier(DesignLanguages.cupertino);
  // the design language is reset upon every restart
  runApp(DesignLanguageDispatcher(
    material: (_, __) => const MyApp(),
    cupertino: (_, __) => const MyIosApp(), // all platforms will select this by default
    macos: (_, __) => const MyMacosApp(),
  ));
}

It is also possible to load at startup the design language that had been saved to persistance storage in a previous session.

// in a previous session:
sharedPreferences.setString('design_language', DesignLanguage.current.toString());

// when the app starts:
Future<void> main() async {
  final sharedPreferences = await SharedPreferences.getInstance();
  final previous = sharedPreferences.getString('design_language');
  final previousDesignLanguage = DesignLanguage.fromString(previous); // if null or invalid, a platform-specific fallback value will be chosen
  DesignLanguage.notifier = DesignLanguageNotifier(previousDesignLanguage);
  runApp(DesignLanguageDispatcher(
    material: (_, __) => const MyApp(),
    cupertino: (_, __) => const MyIosApp(),
    macos: (_, __) => const MyMacosApp(),
  ));
}

How to change the design language

You can change the platform by accessing DesignLanguage's setter chosenDesignLanguage, e.g.: `

ElevatedButton(
    onPressed: () => DesignLanguage.notifier.chosenDesignLanguage =
        DesignLanguages.material,
    child: const Text('set material'),
),

Or you can also reset this setting.

ElevatedButton(
    onPressed: () => DesignLanguage.notifier.chosenDesignLanguage = 
        DesignLanguage.fromPhysicalPlatform,
    child: const Text('reset'),
),

DesignLanguages

DesignLanguages is a class containing all possible DesignLanguage values as static fields. The constructors of DesignLanguages and DesignLanguage are both private.

N.B.: The default and current design languages are accessed through DesignLanguage (and not through DesignLanguages):

  • DesignLanguage.fromPhysicalPlatform
  • DesignLanguage.current (once the notifier is set)

DesignLanguageDispatcher #

DesignLanguageDispatcher is used for dispatching a widget based on the design language.

DesignLanguageDispatcher(
  material: (_, __) => const MyApp(child: const CommonSubtree()),
  cupertino: (_, __) => const MyIosApp(child: const CommonSubtree()),
  macos: (_, __) => const MyMacosApp(child: const CommonSubtree()),
);

Optional child

It is possible to pass a child avoid repeating it in all builders. The child will not get rebuilt when the design language changes. The child should not be a widget of the Material or Cupertino family, but a design-language neutral one. The child can nest DesignLanguageDispatchers.

Rewritten example above:

DesignLanguageDispatcher(
  child: CommonSubtree(arg1: 1, arg2: 'myTitle'), // inside it there might be other widgets using DesignLanguageDispatcher
  material: (_, child) => const MyApp(child: child),
  cupertino: (_, child) => const MyIosApp(child: child),
  macos: (_, child) => const MyMacosApp(child: child),
);

matchDesignLanguage #

You can invoke matchDesignLanguage in case you need to invoke some design-language-specific functions, e.g.:

MyImage( // widget used under all design languages (in our case material, cupertino and macos)
  ...
  onPressed: () {
    matchDesignLanguage(
      cupertino: () => showCupertinoModalPopup(...),
      material: () => showModalBottomSheet(...),
      macos: () => showMacosModalPopup(...),
    );
  },
)

Overrides #

If you don't like the default values this package assigns, feel free to override them with DesignLanguage.overrides:

// inside main:
DesignLanguage.overrides = {"linux": DesignLanguages.macos, "ios": DesignLanguages.material};
2
likes
160
points
23
downloads

Publisher

verified publishermanuelplavsic.ch

Weekly Downloads

A package that makes cross-design-language development a breeze.

Repository (GitLab)
View/report issues

Documentation

API reference

License

BSD-3-Clause (license)

Dependencies

flutter

More

Packages that depend on design_language