• Mdc-103: Material Theming with Color, Shape, Elevation, and Type (Flutter)
  • The original author: codelabs.developers.google.com
  • The Nuggets translation Project
  • Permanent link to this article: github.com/xitu/gold-m…
  • Translator: DevMcryYu
  • Proofreader: PrinceChou, Fengziyin1234

Mdc-103: Material Theming color, shape, height and type of Flutter

1. Introduction

material.io/develop

You can now use MDC to customize your applications in styles far more unique than before. Material Design’s recent updates give designers and developers more flexibility in expressing their product ideas.

In tutorials MDC-101 and MDC-102, you use the Material component (MDC) to build the foundation for an e-commerce application called Shrine that sells clothing and home items. The app’s user flow consists of an initial landing page and then a navigation to the home screen that displays the product.

You’re going to build one

In this tutorial, you will customize the Shrine app using the following properties:

  • Color
  • Typography
  • Height (Elevation)
  • Shape
  • Layout (Layout)

This is the third of four tutorials to guide you through building the Shrine application.

The rest of the tutorial can be found here:

  • Mdc-101: Material Components (MDC) Foundation (Flutter)
  • Mdc-102: Material structure and layout
  • Mdc-104: Material Design Advanced components

By the end of MDC-104, you will have built an application that looks like this:

Mdc-flutter components and subsystems used in this tutorial

  • Theme (Theme)
  • Typography
  • Height (Elevation)
  • Image List

You will need to

  • Flutter SDK
  • Install the Flutter plugin in Android Studio, or your favorite code editor
  • The sample code

To build and run the Flutter application on iOS, you need to meet the following requirements:

  • A computer running macOS
  • Xcode 9 or later
  • IOS emulators, or iOS physical devices

To build and run the Flutter application on Android, you need to meet the following requirements:

  • A computer running macOS, Windows, or Linux
  • Android Studio
  • Android emulator (shipped with Android Studio) or Android physical device

2. Install the Flutter environment

The premise condition

To start developing mobile apps with Flutter, you need to:

  • Flutter SDK
  • IntelliJ IDE with the Flutter plugin, or your favorite code editor

Flutter’s IDE tools are available for Android Studio, IntelliJ IDEA Community (free) and IntelliJ IDEA Ultimate.

  • A computer running macOS
  • Xcode 9 or later
  • IOS emulators, or iOS physical devices

  • A computer running macOS, Windows, or Linux
  • Android Studio
  • Android emulator (shipped with Android Studio) or Android physical device

Get detailed Flutter installation information

Important: If the Allow USB Debugging dialog box appears on your Android phone connected to your computer, enable the Always Allow from this computer option, and then click OK.

Before continuing with this tutorial, make sure your SDK is in the right state. If you have previously installed the Flutter SDK, use The Flutter Upgrade to ensure that the SDK is up to date.

flutter upgrade
Copy the code

Running flutter Upgrade will automatically run flutter Doctor. If this is the first time that a Flutter is installed and no upgrade is required, run the Flutter Doctor manually. View all the ✓ markers displayed. This will download any missing SDK files you need and make sure your computer is properly configured to develop Flutter.

flutter doctor
Copy the code

3. Download the tutorial starter application

Continue from MDC-102?

If you are done with MDC-102, the code for this tutorial should be ready. Skip to adjusting colors.

From scratch?

Download the initial application

Download starter app

This entry program is located in the material- Components -flutter-codelabs-103-starter_and_102-complete/ mdC_100_series directory.

. Or clone it from GitHub

To clone this project from GitHub, run the following command:

git clone https://github.com/material-components/material-components-flutter-codelabs.git
cd material-components-flutter-codelabs
git checkout 103-starter_and_102-complete
Copy the code

More help: Clone the repository from GitHub

Right branch

Tutorial MDC-101 to 104 continuous build. So when you finish the 103 code, it will become the initial code for the 104 tutorial! The code is divided into different branches, and you can list them all using the following command:

git branch --list

To see the complete code, switch to the branch 104-starter_and_103-complete.

Build your project

The default for the following steps is Android Studio (IntelliJ).

Create a project

  1. In terminal, navigate to the Material – Components -flutter- Codelabs

  2. Run the FLUTTER create MDC_100_series

Open the project

  1. Open Android Studio.

  2. If you see the welcome page, click to open your existing Android Studio project.

  1. Navigate to thematerial-components-flutter-codelabs/mdc_100_seriesDirectory and click Open, which will open the project.

You can ignore any errors you see in the analysis until you build the project once.

  1. In the project panel on the left, delete the test file../test/widget_test.dart

  1. If prompted, install all platforms and plugin updates or FlutterRunConfigurationType, and then restart the Android Studio.

Tip: Make sure you have the Flutter and Dart plug-ins installed.

Run the initial program

The following steps are performed by default on an Android emulator or device. You can also do this on an iOS emulator or device, as long as you have Xcode installed.

  1. Select device or emulator

If the Android emulator is not already running, choose Tools -> Android -> AVD Manager to create your device and start the emulator. If the AVD already exists, you can start the emulator directly from IntelliJ’s device selector, as shown in the next step.

(For iOS emulators, if it is not already running, start it on your development Device by selecting Flutter Device Selection -> Open iOS Simulator.)

  1. Start Flutter application:
  • Look for the Flutter Device Selection drop-down menu at the top of your editor window and select the Device (for example, iPhone SE/Android SDK Built for).
  • Click on therunIcon (

    ).

If you cannot run the application successfully, stop to resolve your development environment issues. Try to navigate to the Material – Components -flutter-codelabs; If you download the.zip file in terminal, navigate to the material-components-flutter-codelabs-… Then run the FLUTTER create MDC_100_series.

Success! The Shrine login page from the previous tutorial should now be running in your emulator. You can see the logo of Shrine and the name “Shrine” underneath it.

If the app is not updated, click the “Play” button again, or click the “Stop” after “Play”.

Click “Next” to see the home screen from the previous tutorial.

Step 4 Adjust Color

A color scheme representing the Shrine brand has been created. The designers want you to implement this color scheme in the Shrine app.

First, let’s import these colors into the project.

create colors.dart

Create a new dart file called colors.dart in the lib directory. Import the Material component and add the Color constant:

import 'package:flutter/material.dart';

const kShrinePink50 = const Color(0xFFFEEAE6);
const kShrinePink100 = const Color(0xFFFEDBD0);
const kShrinePink300 = const Color(0xFFFBB8AC);
const kShrinePink400 = const Color(0xFFEAA4A4);

const kShrineBrown900 = const Color(0xFF442B2D);

const kShrineErrorRed = const Color(0xFFC5032B);

const kShrineSurfaceWhite = const Color(0xFFFFFBFA);
const kShrineBackgroundWhite = Colors.white;
Copy the code

Customize the Color Palette

This color theme is created with a designer’s choice of colors (as shown below). It contains the Shrine brand color and applies it to the Material theme editor, resulting in a complete palette. (The colors are not from the 2014 Material Color Palette.)

The Material theme editor uses shade, a numeric shade, to sort colors, each with 50, 100, 200… All the way up to 900 and a few shades. Shrine only uses 50, 100 and 300 shades of pink and 900 shades of brown.

Chroma: Degree of shade, lightness of color.

The color parameters for each part correspond to the colors in this template. For example, the modifier color of a text box when it receives input should be the Primary color of the theme. If the color does not fit (easily distinguishable from the background), use PrimaryVariant instead.

Colors class

The value of kShrineBackgroundWhite comes from the Colors class. This class contains common color values, such as white. It also includes the 2014 Color Palette as the MaterialColor class.

MaterialColor class

The MaterialColor class (subclass ColorSwatch) found in ‘Material /colors.dart’ is a set of 14 or fewer colors transformed from primary colors, such as 14 different shades of red, green, light green, or stone gray. This is similar to the gradient color cards you see at the paint store.

These colors were introduced in the 2014 Material Guide and are still available in the current guide (Color System) and MDC-FLUTTER. To access them in code, simply call the base color followed by chromaticity (usually a multiple of 100). For example, Pink 400 can be retrieved by colors.pink [400].

You can use these palettes in your design and code. If you already have your own color palette, you can use the palette generation tool or the Material theme editor to create your own color palette.

Now we have the colors we want to use. We can apply it to the UI. We will do this by setting up the ThemeData widget applied to the top hierarchy of the MaterialApp instance.

Custom ThemeData. Light ()

Flutter contains some built-in themes. The Light theme is one of them. Instead of building a ThemeData widget from scratch, we copied the Light theme and then modified some of its properties to customize it for our application.

Copy the ThemeData instance

We call copyWith() in the default light ThemeData and pass in some custom property values. (copyWith() is a common method in Flutter and you’ll see it in many classes and widgets.) This command returns the part instance that matches the instance on which it was called, but replaces some specified values.

Why not instantiate a ThemeData and set its properties? Of course you can! This will make a lot of sense if we continue to build our program. Because ThemeData has a large number of properties, to save time, our tutorial will start by modifying the visible values of an attractive theme. When we try to use alternative themes later, we’ll start with ThemeData that comes with MDC-FLUTTER.

Learn more about ThemeData in the Flutter documentation.

Let’s import colors.dart in app.dart.

import 'colors.dart';
Copy the code

Then add the following outside of app.dart’s ShrineApp class:

// TODO: Build Shrine theme (103) Final ThemeData _kShrineTheme = _buildShrineTheme(); ThemeData_buildShrineTheme() {
  final ThemeData base = ThemeData.light();
  returnbase.copyWith( accentColor: kShrineBrown900, primaryColor: kShrinePink100, buttonColor: kShrinePink100, scaffoldBackgroundColor: kShrineBackgroundWhite, cardColor: kShrineBackgroundWhite, textSelectionColor: KShrinePink100, errorColor: kShrineErrorRed, // TODO: Add text theme (103) // TODO: Add icon theme (103) // TODO: modify input content (103); }Copy the code

Now set theme: to our new theme at the end of the build() function of the application (in the MaterialApp widget) :

// TODO: Add theme (103)return MaterialApp(
  title: 'Shrine'// TODO: change home: to HomePage frontLayer (104) home: $HomePage(), // TODO: returns _currentCategory (104) // TODO: returns _currentCategory (104) // TODO: returns _currentCategory (104) // TODO: Change the backLayer field value to CategoryMenuPage (104) initialRoute:'/login'OnGenerateRoute: _getRoute, theme: _kShrineTheme, // new code);Copy the code

Click the Run button and your login page should look something like this:

Your home screen should look like this:

Notes on colors and themes:

  • You can customize the colors in the UI to interpret your brand.
  • Start with a palette of two colors (primary and secondary), using different shades of color. Or use the Material Design palette tool.
  • Don’t forget typographic colors!
  • Make sure the color contrast between the text and the background is just right (3:1 for primary text, 4:1 for secondary text)

5. Modify the layout and label styles

In addition to changing the color, the designer also provided us with specific typography. The ThemeData of Flutter contains three text themes. Each text topic is a collection of text styles, such as “Headline” and “title.” We will use several styles and change some values for our application.

Custom text themes

To import the fonts into the project, we must add them to the pubspec.yaml file.

In pubspec.yaml, add the following content under the flutter: tag:

  # TODO: Introducing fonts (103)
  fonts:
    - family: Rubik
      fonts:
        - asset: fonts/Rubik-Regular.ttf
        - asset: fonts/Rubik-Medium.ttf
          weight: 500
Copy the code

Now you can access and use the Rubik font.

The pubSpec file is faulty

If you cut and paste the declaration code above, you may get an error when running pub get. If an error occurs, delete the leading space and replace it with a space indent.

fonts:
Copy the code

I had two Spaces before,

family: Rubik
Copy the code

There are four Spaces, and so on.

If you see Mapping values are not allowed here, check the indentation of the line in question and the other lines above.

In app.dart, add the following after _buildShrineTheme() :

TextTheme _buildShrineTextTheme(TextTheme base) {// TODO: buildShrineTextTheme(103) TextTheme _buildShrineTextTheme(TextTheme base) {returnbase.copyWith( headline: base.headline.copyWith( fontWeight: FontWeight.w500, ), title: base.title.copyWith( fontSize: CopyWith (fontWeight: fontweight.w400, fontSize: 14.0,),).apply(fontFamily:'Rubik',
    displayColor: kShrineBrown900,
    bodyColor: kShrineBrown900,
  );
}
Copy the code

This requires a text theme and changes to the styling of Headline, titles, and Captions.

Applying fontFamily in this way only applies the change to the headline, title, caption ratio specified in the copyWith() field.

For some fonts, we are setting custom FontWeight. The FontWeight widget has a convenient value at 100s. In fonts, W500 (weight 500) is medium size and W400 is regular size.

Use a new text theme

The text theme

Text themes are an effective way to ensure that all text in your application is consistent and readable. For example, the text theme style can be black or white, depending on the brightness of the theme’s main color. This ensures that the text contrasts properly with the background and is always readable.

Learn more about text topics in the Flutter documentation.

Add the following to the errorColor of _buildShrineTheme:

// TODO: add textTheme (103) textTheme: _buildShrineTextTheme(base.texttheme), primaryTextTheme: _buildShrineTextTheme(base.primaryTextTheme), accentTextTheme: _buildShrineTextTheme(base.accentTextTheme),Copy the code

Click the Allow button again after clicking the stop button.

The text on the landing page and the home screen looks a little different — some in Rubik font, others in brown rather than black or white.

Notes on typesetting:

  • When choosing text fonts, choose clear fonts for small and body text rather than focusing on styles.
  • Large text fonts used for headings should be used to express or emphasize the brand.

Notice that our ICONS are still white because they have a different theme.

Use custom main icon themes

Add it to the _buildShrineTheme() function:

// TODO: add iconTheme (103) primaryIconTheme: base.icontheme. CopyWith (color: kShrineBrown900),Copy the code

Click the Run button.

The app icon has turned brown!

Contract text

Our labels are a little too big.

In home.dart, change the innermost column of the children: field:

Children: <Widget>[// TODO: handle overflow tags (103) Text(product == null?' ' : product.name,
    style: theme.textTheme.button,
    softWrap: false, overflow: textoverflow. ellipsis, maxLines: 1,), SizedBox(height: 4.0), Text(product == null?' ': formatter.format(product.price), style: theme.textTheme.caption,),Copy the code

Center the text

We want to center the label and align the text with the bottom of each card, not the bottom of the image.

Move the labels to the end (bottom) of the spindle and center them:

/ / TODO: (103) at the center of the tag at the bottom of the alignment and mainAxisAlignment: mainAxisAlignment. End, crossAxisAlignment: crossAxisAlignment. Center,Copy the code

Save the project.

It’s close, but the text is not centered on the card.

Change the horizontal alignment of the parent column:

/ / TODO: card center content (103) crossAxisAlignment: crossAxisAlignment. Center,Copy the code

Save the project. Your app should look like this:

That looks better.

Thematic text box

You can also use InputDecorationTheme to theme the decoration of a text box.

In the _buildShrineTheme() method in app.dart, specify the value of inputDecorationTheme: :

InputDecorationTheme: inputDecorationTheme (border: OutlineInputBorder(),),Copy the code

The text box now has a filled modifier. Let’s remove it.

Within login.dart, remove the filled: true value:

/ / remove filled:trueValue (103) TextField(Controller: _usernameController, decoration: InputDecoration)true
    labelText: 'Username',),), SizedBox(height: 12.0), TextField(Controller: _passwordController, decoration: InputDecoration)true
    labelText: 'Password',
  ),
  obscureText: true,),Copy the code

Click the Stop button, and then click Run (to start the application from scratch). Your login page should look like this when the username text field is active (when you type) :

Enter in the correct accent color text box modifier and floating placeholder rendering. But we can’t see it easily. For those who can’t distinguish between high enough color contrast pixels. (See the “Accessible colors” color article in the Material guide for more details.) Let’s create a special class to override the accent color of the part and make it the PrimaryVariant that the designer provided for us in the color theme above.

Add the following outside the scope of any other class in login.dart:

/ / TODO: Class AccentColorOverride extends StatelessWidget {const AccentColorOverride({Key Key, this.color, this.child}) : super(key: key); final Color color; final Widget child; @override Widget build(BuildContext context) {returnTheme( child: child, data: Theme.of(context).copyWith(accentColor: color), ); }}Copy the code

Next, apply AccentColorOverride to the text box.

In login.dart, import colors:

import 'colors.dart';
Copy the code

Wrap the Username text box with a new widget:

// [Name] AccentColorOverride(color: kShrineBrown900, child: TextField( controller: _usernameController, decoration: InputDecoration( labelText:'Username',),),),Copy the code

Also wrap the Password text box with the new widget:

// [Password] AccentColorOverride(color: kShrineBrown900, child: TextField( controller: _passwordController, decoration: InputDecoration( labelText:'Password',),),),Copy the code

Click the Run button.

6. Adjust height

Now that you’ve set the page to match the specific colors and typography of Shrine, let’s take a look at the card showing the Shrine product. The cards are located on a white surface next to the navigation.

Adjust card height

Dart adds an elevation to the card: value:

// TODO: adjust card height (103) elevation: 0.0,Copy the code

Save your project.

You have now removed the shadow under the card.

Let’s change the height of the landing page component to complete it.

Adjust the height of the NEXT button

The default height of RaisedButton is 2. Let’s turn it up a little bit.

Dart add elevation to NEXT RaisedButton:

RaisedButton(
  child: Text('NEXT'Elevation: 8.0, // Add new codeCopy the code

Click the Stop button, and then click Run. Your landing page should look something like this:

Elevation:

  • All Material Design surfaces and components have height values.
  • The separation between the end of one plane and the beginning of another plane is distinguished by the edges of the plane.
  • The height difference between the surfaces can be represented by a dim or bright background or shadow.
  • Planes in front of other planes usually contain more important content.

7. Add shapes

Shrine defines an octagonal or rectangular element with a cool geometric style. Let’s implement shape styles in the cards on the home screen and in the text fields and buttons on the login screen.

Change the shape of the text field on the login screen

In app.dart, import the special cut Corners border file:

import 'supplemental/cut_corners_border.dart';
Copy the code

Again in app.dart, add a shape with a cut corner to the trim theme of the text field:

InputDecorationTheme: inputDecorationTheme (border: CutCornersBorder(), // Replace the code),Copy the code

Change the button shape on the login screen

In login.dart, add a beveled rectangle border to the CANCEL button:

FlatButton(
  child: Text('CANCEL'), Shape: RectangleBorder(borderRadius: borderRadius. All (Radius. Circular (7.0)),),Copy the code

FlatButton has no visible shape, so why add a border shape? When touched this way, the ripple animation will bind to the same shape.

Now add the same shape to the NEXT button:

RaisedButton(
  child: Text('NEXT'), elevation: 8.0, Shape: Rectangleborder (borderRadius: borderRadius. All (Radius. Circular (7.0)),Copy the code

Notes on shapes:

  • The use of shapes promotes the visual expression of the brand.
  • Shapes have adjustable curves and angle-free corners, curves and corners, and the total number of corners.
  • The shape of the component should not interfere with its usability!

Click the Stop button and then click Run:

8. Modify the layout

Next, let’s change the layout to show cards of different aspect ratios and sizes so that each card looks different.

Replace the GridView with an AsymmetricView

We have documented asymmetrical layouts.

In home.dart, modify all of the following files:

import 'package:flutter/material.dart';

import 'model/products_repository.dart';
import 'model/product.dart';
import 'supplemental/asymmetric_view.dart'; Class HomePage extends StatelessWidget {// TODO: Override Widget build(BuildContext context) {TODO: returns an AsymmetricView (104) // TODO: Pass the Category variable to AsymmetricView (104)return Scaffold(
      appBar: AppBar(
        brightness: Brightness.light,
        leading: IconButton(
          icon: Icon(Icons.menu),
          onPressed: () {
            print('Menu button');
          },
        ),
        title: Text('SHRINE'),
        actions: <Widget>[
          IconButton(
            icon: Icon(Icons.search),
            onPressed: () {
              print('Search button');
            },
          ),
          IconButton(
            icon: Icon(Icons.tune),
            onPressed: () {
              print('Filter button'); }, ), ], ), body: AsymmetricView(products: ProductsRepository.loadProducts(Category.all)), ); }}Copy the code

Save the project.

The product now rolls horizontally in a woven pattern style. Also the status bar text (top time and network) is now black. That’s because we changed the AppBar to Be Light, thumbnails: Thumbnails

9. Try another topic

Color is an effective way to interpret a brand, and a small change in color can have a big impact on your user experience. To test this, let’s see what Shrine would look like if the brand had a completely different color scheme.

Change the color

In colors.dart, add the following:

const kShrineAltDarkGrey = const Color(0xFF414149);
const kShrineAltYellow = const Color(0xFFFFCF44);
Copy the code

In app.dart, modify the _buildShrineTheme() and _buildShrineTextTheme methods as follows:

ThemeData _buildShrineTheme() {
  final ThemeData base = ThemeData.dark();
  return base.copyWith(
    accentColor: kShrineAltDarkGrey,
    primaryColor: kShrineAltDarkGrey,
    buttonColor: kShrineAltYellow,
    scaffoldBackgroundColor: kShrineAltDarkGrey,
    cardColor: kShrineAltDarkGrey,
    textSelectionColor: kShrinePink100,
    errorColor: kShrineErrorRed,
    textTheme: _buildShrineTextTheme(base.textTheme),
    primaryTextTheme: _buildShrineTextTheme(base.primaryTextTheme),
    accentTextTheme: _buildShrineTextTheme(base.accentTextTheme),
    primaryIconTheme: base.iconTheme.copyWith(
      color: kShrineAltYellow
    ),
    inputDecorationTheme: InputDecorationTheme(
      border: CutCornersBorder(),
    ),
  );
}

TextTheme _buildShrineTextTheme(TextTheme base) {
  returnbase.copyWith( headline: base.headline.copyWith( fontWeight: FontWeight.w500, ), title: base.title.copyWith( fontSize: CopyWith (fontWeight: fontweight.w400, fontSize: 14.0,),).apply(fontFamily:'Rubik',
    displayColor: kShrineSurfaceWhite,
    bodyColor: kShrineSurfaceWhite,
  );
}
Copy the code

In login.dart, turn the diamond logo white:

Image.asset(
  'assets/diamond.png', color: kShrineBackgroundWhite, // add code),Copy the code

Again in login.dart, change the emphasis color overlay for the two text fields to yellow:

AccentColorOverride(color: kShrineAltYellow, // modify code child: TextField(controller: _usernameController, decoration: InputDecoration( labelText:'Username',),),), SizedBox(height: 12.0), AccentColorOverride(color: kShrineAltYellow, // modify code child: TextField(controller: _passwordController, decoration: const InputDecoration( labelText:'Password',),),),Copy the code

In Home. dart, change the Brightness to Dark:

brightness: Brightness.dark,
Copy the code

Save the project. It’s time for a new theme.

The results were very different! Let’s restore this color code before moving on to tutorial 104.

Download the MDC-104 initial code

10. Summary

So far, you have created an application designed according to the designer’s specifications.

The complete MDC-103 application can be found in the 104-starter_and_102-complete branch.

You can test your version of the page against applications in this branch.

The next step

You have now used the following MDC components: theme, layout, height, and shape. You can explore more components and subsystems in the MDC-FLUTTER library.

Dig into the Files in the Supplemental directory to see how we make horizontally scrolling, asymmetrical layout grids.

What if your application design contains component elements that are not in the MDC library? In MDC-104: Material Design Advanced Components we will show how to use MDC libraries to create custom components to achieve a specific look and feel.

If you find any mistakes in your translation or other areas that need to be improved, you are welcome to the Nuggets Translation Program to revise and PR your translation, and you can also get the corresponding reward points. The permanent link to this article at the beginning of this article is the MarkDown link to this article on GitHub.


The Nuggets Translation Project is a community that translates quality Internet technical articles from English sharing articles on nuggets. The content covers Android, iOS, front-end, back-end, blockchain, products, design, artificial intelligence and other fields. If you want to see more high-quality translation, please continue to pay attention to the Translation plan of Digging Gold, the official Weibo, Zhihu column.