Amazon.co.uk Widgets

Introduction

This is the fourth part of a journey to build and publish a Flutter™ based app using Material Components for Flutter (MDC-Flutter).

Dark and light appearance

All iOS and Android devices before Android 10 and iOS 13 had one appearance - light appearance. Dark theme was introduced in Android 10, and Dark appearance in iOS 13. throughout this journey the word 'appearance' will be used for system setting and 'theme' will just be about the app being built.

Dark appearance has proven very popular among end users due to the better usability in low light and perhaps claimed battery improvements. There won't be any new devices that don't support it so light only devices has become a legacy support issue now. This means that supporting the system settings that change the device from light to dark appearance must be supported for apps so as not to look anachronistic on new devices. So lets revisit the Material guidelines for dark themes.

Behaviour

The guidelines talk about having a setting in the app. This app will simply respect the system setting for the device. There won't be a separate control. This seems to be a more usual expected behaviour for apps, and is less work!

Baseline Material color theme and dark theme baseline palette

The 2014 baseline theme as originally designed had 12 colours named and defined. The dark theme baseline palette more recently added only has 11 colours. Secondary variant is no more. No idea why. Nevertheless it is important to define all these colours for our theme so as to make sure that the app displays as expected on all supported devices. Importantly remember the device can determine automatically whether to switch from light to dark appearance by time of day, rule or external sensor for example. Take the colour table from the previous article and modify it for dark appearance so as to see the entire colour pallette. This is why in the last article we created the darkwhichislight palette in addition to the lightwhichisdark one.

Primary
500
#6200EE
Primary
200
#BB86FC
Primary Variant
700
#3700B3
Primary Variant
700
#3700B3
Secondary
200
#03DAC6
Secondary
200
#03DAC6
Secondary Variant
#018786
 
Background
#FFFFFF
Background
#121212
Surface
#FFFFFF
Surface
#121212
Error
#B00020
Error
#CF6679
On Primary
#FFFFFF
On Primary
#000000
On Secondary
#000000
On Secondary
#000000
On Background
#000000
On Background
#FFFFFF
On Surface
#000000
On Surface
#FFFFFF
On Error
#FFFFFF
On Error
#000000

The . The "On" colors above are primarily applied on top of key surfaces that use a primary, secondary, surface, background, or error color. By default, dark theme “on” colors are white and black. When adjusting the custom theme these will mainly stay on the defaults.

Custom Material color theme extended to cover dark appearance

Putting the two themes like this is helpful to identify any clashes.

Primary
500
#892807
Primary
200
#EC7C55
Primary Variant
700
#570000
Primary Variant
700
#E76944
Secondary
200
#ec7c55
Secondary
200
#F6BEAA
Secondary Variant
#bf5531
 
Background
#FFFFFF
Background
#121212
Surface
#FFFFFF
Surface
#121212
Error
#C5032B
Error
#CF6679
On Primary
#FFFFFF
On Primary
#000000
On Secondary
#000000
On Secondary
#000000
On Background
#000000
On Background
#FFFFFF
On Surface
#000000
On Surface
#FFFFFF
On Error
#FFFFFF
On Error
#000000

Apply the custom colours to your theme in the app

Edit main.dart. Note that swatches are groups of colours in material shades, and named individual colours need to be identified specifically even if they are a part of a swatch.

To use the elements of existing themes and just define the aspects of the theme that concern your app ise the copywith method on Theme.of(context). This looks up the widget tree and returns the first theme found which is the default theme, and creates a theme for this apps context with the changes we have defined merged into the default theme.


theme: ThemeData(
  primarySwatch: lightwhichisdarker,
  primaryColor: lightwhichisdarker[500],
  scaffoldBackgroundColor: parchmentLightBackground,
    textTheme: Theme.of(context).textTheme.copyWith(
      headline1: TextStyle(color: parchmentLightOnSurface),
          headline2: TextStyle(color: parchmentLightOnSurface),
          headline3: TextStyle(color: parchmentLightOnSurface),
          headline4: TextStyle(color: parchmentLightOnSurface),
          headline5: TextStyle(color: parchmentLightOnSurface),
          headline6: TextStyle(color: parchmentLightOnSurface),
          subtitle1: TextStyle(color: parchmentLightOnSurface),
          subtitle2: TextStyle(color: parchmentLightOnSurface),
          bodyText1: TextStyle(color: parchmentLightOnSurface),
          bodyText2: TextStyle(color: parchmentLightOnSurface),
          button: TextStyle(color: parchmentLightOnSurface),
          caption: TextStyle(color: parchmentLightOnSurface),
          overline: TextStyle(color: parchmentLightOnSurface),
    ),
  ),
  
  ...
  
darkTheme: ThemeData(
  primarySwatch: darkwhichislighter,
  primaryColor: darkwhichislighter[500],
  scaffoldBackgroundColor: parchmentDarkBackground,
    textTheme: Theme.of(context).textTheme.copyWith(
       headline1: TextStyle(color: parchmentDarkOnSurface),
          headline2: TextStyle(color: parchmentDarkOnSurface),
          headline3: TextStyle(color: parchmentDarkOnSurface),
          headline4: TextStyle(color: parchmentDarkOnSurface),
          headline5: TextStyle(color: parchmentDarkOnSurface),
          headline6: TextStyle(color: parchmentDarkOnSurface),
          subtitle1: TextStyle(color: parchmentDarkOnSurface),
          subtitle2: TextStyle(color: parchmentDarkOnSurface),
          bodyText1: TextStyle(color: parchmentDarkOnSurface),
          bodyText2: TextStyle(color: parchmentDarkOnSurface),
          button: TextStyle(color: parchmentDarkOnSurface),
          caption: TextStyle(color: parchmentDarkOnSurface),
          overline: TextStyle(color: parchmentDarkOnSurface),
    ),
   ),


Make the app show you the theme

It can be helpful to have a page in the app which shows you the common components and what they look like. This is useful for testing different devices, however you will need to make test pages do not appear in the production app. Test data like 'lorem ipsum' text will fail Apple's App Store review guidelines.


     ),
      body: Center(
      //  child: RaisedButton(
         child: Padding(
           padding: EdgeInsets.all(16.0),
             child: Text('Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur eget justo non lacus ullamcorper rhoncus. Nulla sagittis erat non tortor feugiat, porta rhoncus ante fringilla. Suspendisse vulputate leo nisi, et sagittis augue luctus sollicitudin. Donec feugiat sed sapien in vehicula. Nunc auctor blandit lorem vel malesuada. Curabitur sit amet mattis urna, sit amet ornare augue. Mauris luctus metus vitae vehicula dictum. Sed posuere turpis sit amet nisi tristique cursus. Etiam eget facilisis lacus. Sed ac nisi ullamcorper, molestie ligula eget, suscipit libero. In blandit a eros ac scelerisque. Nunc imperdiet erat neque, eu fermentum justo faucibus quis.',
               style: Theme.of(context).textTheme.headline6,
         )

Dark and light text theme screenshots

This is just some boilerplate text. It is in headline6 text style. headline6 is parchmentLightOnSurface in the light theme and parchmentDarkOnSurface on the dark theme and should change colour when the theme is changed. This is so simple compared to writing specific code to support colour changes.

Flutter Material Components Android R headline6 iOS Light appearance   Flutter Material Components Android R headline6 Dark appearance

(Google Pixel 2XL, Android R beta)

Lets add some more components to the home page of the app.