MDC-103 Flutter: Material Theming mit Farbe, Form, Höhe und Typ

1. Einführung

logo_components_color_2x_web_96dp.png

Material Components (MDC) helfen Entwicklern bei der Implementierung von Material Design. MDC wurde von einem Team aus Entwicklern und UX-Designern bei Google entwickelt und bietet Dutzende von ansprechenden und funktionalen UI-Komponenten. Es ist für Android, iOS, das Web und Flutter verfügbar.material.io/develop

Mit Material Flutter können Sie das unverwechselbare Design Ihrer Apps jetzt noch besser anpassen. Durch die jüngste Erweiterung von Material Design haben Designer und Entwickler mehr Flexibilität, die Marke ihres Produkts zu präsentieren.

In den Codelabs MDC-101 und MDC-102 haben Sie mit Material Flutter die Grundlagen einer App namens Shrine erstellt,einer E‑Commerce-App, in der Kleidung und Haushaltswaren verkauft werden. Diese App enthält einen User Flow, der mit einem Anmeldebildschirm beginnt und den Nutzer dann zu einem Startbildschirm mit Produkten führt.

Umfang

In diesem Codelab passen Sie die Shrine-App mit den folgenden Tools an:

  • Farbe
  • Typografie
  • Höhe
  • Form
  • Layout

Android

iOS

Anmeldeseite für einen Schrein in Braun und Rosa

Anmeldeseite für einen Schrein in Braun und Rosa

Produktseite von Shrine mit einer oberen App-Leiste und einem asymmetrischen, horizontal scrollbaren Raster voller Produkte in Pink

Material-Flutter-Komponenten und ‑Subsysteme in diesem Codelab

  • Designs
  • Typografie
  • Höhe
  • Bildliste

Wie würden Sie Ihre Erfahrung mit der Flutter-Entwicklung bewerten?

Anfänger Mittelstufe Fortgeschritten

2. Flutter-Entwicklungsumgebung einrichten

Für dieses Lab benötigen Sie zwei Softwarekomponenten: das Flutter SDK und einen Editor.

Sie können das Codelab auf einem der folgenden Geräte ausführen:

  • Ein physisches Android- oder iOS-Gerät, das mit Ihrem Computer verbunden ist und auf den Entwicklermodus eingestellt ist.
  • Der iOS-Simulator (erfordert die Installation von Xcode-Tools).
  • Android Emulator (Einrichtung in Android Studio erforderlich)
  • Ein Browser (für das Debugging ist Chrome erforderlich).
  • Als Windows-, Linux- oder macOS-Desktopanwendung. Sie müssen auf der Plattform entwickeln, auf der Sie die Bereitstellung planen. Wenn Sie also eine Windows-Desktop-App entwickeln möchten, müssen Sie unter Windows entwickeln, um auf die entsprechende Build-Kette zuzugreifen. Es gibt betriebssystemspezifische Anforderungen, die auf docs.flutter.dev/desktop ausführlich beschrieben werden.

3. Starter-App für das Codelab herunterladen

Sie haben bereits MDC-102 absolviert?

Wenn Sie MDC-102 abgeschlossen haben, sollte Ihr Code für dieses Codelab bereit sein. Farben ändern

Sie fangen bei null an?

Starter-App für das Codelab herunterladen

Die Starter-App befindet sich im Verzeichnis material-components-flutter-codelabs-103-starter_and_102-complete/mdc_100_series.

…oder aus GitHub klonen

Führen Sie die folgenden Befehle aus, um dieses Codelab von GitHub zu klonen:

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

Projekt öffnen und App ausführen

  1. Öffnen Sie das Projekt in einem beliebigen Editor.
  2. Folgen Sie der Anleitung unter Erste Schritte: Testlauf für den von Ihnen ausgewählten Editor.

Fertig! Auf Ihrem Gerät sollte die Shrine-Anmeldeseite aus den vorherigen Codelabs angezeigt werden.

Android

iOS

Shrine-Anmeldeseite ohne Design

Shrine-Anmeldeseite ohne Design

Klicken Sie auf „Weiter“, um die Produktseite aufzurufen.

Android

iOS

Seite mit Produktübersicht von Shrine ohne Thema

Seite mit Produktübersicht von Shrine ohne Thema

4. Farben ändern

Es wurde ein Farbschema erstellt, das die Marke Shrine repräsentiert. Der Designer möchte, dass Sie dieses Farbschema in der Shrine App implementieren.

Importieren wir diese Farben zuerst in unser Projekt.

Erstellen colors.dart

Erstellen Sie in lib eine neue Dart-Datei mit dem Namen colors.dart. Importieren Sie material.dart und fügen Sie const Color-Werte hinzu:

import 'package:flutter/material.dart';

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

const kShrineBrown900 = Color(0xFF442B2D);

const kShrineErrorRed = Color(0xFFC5032B);

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

Benutzerdefinierte Farbpalette

Dieses Farbdesign wurde von einem Designer mit benutzerdefinierten Farben erstellt (siehe Abbildung unten). Es enthält Farben, die aus der Marke von Shrine ausgewählt und auf den Material Theme Editor angewendet wurden. Dort wurden sie erweitert, um eine umfassendere Palette zu erstellen. Diese Farben stammen nicht aus den Material-Farbpaletten von 2014.

Im Material Theme Editor sind sie in numerisch gekennzeichnete Schattierungen unterteilt, darunter die Labels 50, 100, 200 … bis 900 für jede Farbe. Für Shrine werden nur die Farbtöne 50, 100 und 300 aus dem rosa Farbmuster und 900 aus dem braunen Farbmuster verwendet.

d0362cb45c565a8e.jpeg 470b0e1c2669ae2.png

Jeder farbige Parameter eines Widgets wird einer Farbe aus diesen Schemata zugeordnet. Die Farbe der Dekorationen eines Textfelds, wenn es aktiv Eingaben empfängt, sollte beispielsweise die primäre Farbe des Designs sein. Wenn diese Farbe nicht barrierefrei ist (d. h. nicht gut vom Hintergrund abhebt), verwenden Sie stattdessen eine andere Farbe.

Nachdem wir die gewünschten Farben haben, können wir sie auf die Benutzeroberfläche anwenden. Dazu legen wir die Werte eines ThemeData-Widgets fest, das wir auf die MaterialApp-Instanz oben in unserer Widget-Hierarchie anwenden.

Thema „light“ anpassen

Flutter enthält einige integrierte Themes. Das helle Theme ist eines davon. Anstatt ein ThemeData-Widget von Grund auf neu zu erstellen, kopieren wir das helle Design und ändern die Werte, um sie für unsere App anzupassen.

colors.dart in app.dart. importieren

import 'colors.dart';

Fügen Sie dann Folgendes in „app.dart“ außerhalb des Bereichs der ShrineApp-Klasse hinzu:

// TODO: Build a Shrine Theme (103)
final ThemeData _kShrineTheme = _buildShrineTheme();

ThemeData _buildShrineTheme() {
  final ThemeData base = ThemeData.light(useMaterial3: true);
  return base.copyWith(
    colorScheme: base.colorScheme.copyWith(
      primary: kShrinePink100,
      onPrimary: kShrineBrown900,
      secondary: kShrineBrown900,
      error: kShrineErrorRed,
    ),
    // TODO: Add the text themes (103)
    // TODO: Decorate the inputs (103)
  );
}

Legen Sie nun theme: am Ende der build()-Funktion von ShrineApp (im MaterialApp-Widget) auf unser neues Theme fest:

  // TODO: Customize the theme (103)
  theme: _kShrineTheme, // New code

Projekt speichern. Ihr Anmeldebildschirm sollte jetzt so aussehen:

Android

iOS

Anmeldeseite für Shrine in Rosa und Braun

Anmeldeseite für Shrine in Rosa und Braun

5. Typografie und Labelstile ändern

Neben den Farbänderungen hat der Designer uns auch eine bestimmte Typografie vorgegeben. Das ThemeData von Flutter enthält drei Text-Themes. Jedes Textdesign ist eine Sammlung von Textformaten wie „Überschrift“ und „Titel“. Wir verwenden einige Stile für unsere App und ändern einige der Werte.

Textdesign anpassen

Wenn Sie Schriftarten in das Projekt importieren möchten, müssen sie der Datei „pubspec.yaml“ hinzugefügt werden.

Fügen Sie in pubspec.yaml Folgendes direkt nach dem Tag flutter: hinzu:

  # TODO: Insert Fonts (103)
  fonts:
    - family: Rubik
      fonts:
        - asset: fonts/Rubik-Regular.ttf
        - asset: fonts/Rubik-Medium.ttf
          weight: 500

Sie können jetzt auf die Schriftart „Rubik“ zugreifen und sie verwenden.

Fehlerbehebung bei der pubspec-Datei

Wenn Sie die Deklaration oben kopieren und einfügen, erhalten Sie möglicherweise Fehler beim Ausführen von pub get. Wenn Fehler auftreten, entfernen Sie zuerst die führenden Leerzeichen und ersetzen Sie sie durch Leerzeichen mit einer Einrückung von zwei Leerzeichen. (Zwei Leerzeichen davor

fonts:

, vier Leerzeichen davor

family: Rubik

usw.)

Wenn Sie die Meldung Mapping values are not allowed here sehen, prüfen Sie den Einzug der Zeile mit dem Problem und den Einzug der Zeilen darüber.

Ändern Sie in login.dart Folgendes in Column():

Column(
  children: <Widget>[
    Image.asset('assets/diamond.png'),
    const SizedBox(height: 16.0),
    Text(
      'SHRINE',
      style: Theme.of(context).textTheme.headlineSmall,
    ),
  ],
)

Fügen Sie in app.dart nach _buildShrineTheme() Folgendes hinzu:

// TODO: Build a Shrine Text Theme (103)
TextTheme _buildShrineTextTheme(TextTheme base) {
  return base
      .copyWith(
        headlineSmall: base.headlineSmall!.copyWith(
          fontWeight: FontWeight.w500,
        ),
        titleLarge: base.titleLarge!.copyWith(
          fontSize: 18.0,
        ),
        bodySmall: base.bodySmall!.copyWith(
          fontWeight: FontWeight.w400,
          fontSize: 14.0,
        ),
        bodyLarge: base.bodyLarge!.copyWith(
          fontWeight: FontWeight.w500,
          fontSize: 16.0,
        ),
      )
      .apply(
        fontFamily: 'Rubik',
        displayColor: kShrineBrown900,
        bodyColor: kShrineBrown900,
      );
}

Dazu wird ein TextTheme verwendet, um die Darstellung von Überschriften, Titeln und Bildunterschriften zu ändern.

Wenn Sie fontFamily auf diese Weise anwenden, werden die Änderungen nur auf die in copyWith() angegebenen Typografieskalawerte (Überschrift, Titel, Untertitel) angewendet.

Für einige Schriftarten legen wir eine benutzerdefinierte Schriftstärke in Schritten von 100 fest: „w500“ (die Stärke 500) entspricht „Mittel“ und „w400“ entspricht „Normal“.

Neue Textdesigns verwenden

Fügen Sie _buildShrineTheme nach dem Fehler die folgenden Themen hinzu:

// TODO: Add the text themes (103)
textTheme: _buildShrineTextTheme(base.textTheme),
textSelectionTheme: const TextSelectionThemeData(
  selectionColor: kShrinePink100,
),

Projekt speichern. Starten Sie die App dieses Mal auch neu (Hot Restart), da wir die Schriftarten geändert haben.

Android

iOS

Produktübersichtsseite für ein Shrine-Produkt mit angewendeten Textthemen

Text auf dem Anmelde- und dem Startbildschirm sieht anders aus: Für einige Texte wird die Schriftart „Rubik“ verwendet und andere werden braun statt schwarz oder weiß gerendert. Symbole werden ebenfalls in Braun gerendert.

Text verkleinern

Die Labels sind zu groß.

Ändern Sie in home.dart die children: der innersten Spalte:

// TODO: Change innermost Column (103)
children: <Widget>[
// TODO: Handle overflowing labels (103)
  Text(
    product.name,
    style: theme.textTheme.button,
    softWrap: false,
    overflow: TextOverflow.ellipsis,
    maxLines: 1,
  ),
  const SizedBox(height: 4.0),
  Text(
    formatter.format(product.price),
    style: theme.textTheme.bodySmall,
  ),
  // End new code
],

Text zentrieren und nach unten verschieben

Wir möchten die Labels zentrieren und den Text am unteren Rand jeder Karte ausrichten, nicht am unteren Rand jedes Bildes.

Verschieben Sie die Labels ans Ende (unten) der Hauptachse und zentrieren Sie sie::

  // TODO: Align labels to the bottom and center (103)
  mainAxisAlignment: MainAxisAlignment.end,
  crossAxisAlignment: CrossAxisAlignment.center,

Projekt speichern.

Android

iOS

Produktübersichtsseite für Schrein mit unterschiedlicher Textausrichtung

Produktübersichtsseite für Schrein mit unterschiedlicher Textausrichtung

Das sieht viel besser aus.

Textfelder gestalten

Sie können die Dekoration von Textfeldern auch mit einem InputDecorationTheme gestalten.

Geben Sie in app.dart in der Methode _buildShrineTheme() einen inputDecorationTheme:-Wert an:

// TODO: Decorate the inputs (103)
inputDecorationTheme: const InputDecorationTheme(
  border: OutlineInputBorder(),
),

Derzeit haben die Textfelder eine filled-Dekoration. Lass uns das entfernen. Wenn Sie filled entfernen und inputDecorationTheme angeben, erhalten die Textfelder den Umrissstil.

Entfernen Sie in login.dart die filled: true-Werte:

// Remove filled: true values (103)
TextField(
  controller: _usernameController,
  decoration: const InputDecoration(
    // Removed filled: true
    labelText: 'Username',
  ),
),
const SizedBox(height: 12.0),
TextField(
  controller: _passwordController,
  decoration: const InputDecoration(
    // Removed filled: true
    labelText: 'Password',
  ),
  obscureText: true,
),

Heißstart. So sollte der Anmeldebildschirm aussehen, wenn das Feld „Nutzername“ aktiv ist (wenn Sie etwas eingeben):

Android

iOS

Anmeldeseite für Shrine mit fokussiertem Feld für den Nutzernamen

Anmeldeseite für Shrine mit fokussiertem Feld für den Nutzernamen

Wenn Sie in ein Textfeld schreiben, werden die Rahmen und schwebenden Labels in der Primärfarbe gerendert. Aber wir können es nicht so einfach sehen. Sie ist nicht für Nutzer mit Sehbeeinträchtigung zugänglich, die Schwierigkeiten haben, Pixel zu unterscheiden, die keinen ausreichend hohen Farbkontrast aufweisen. Weitere Informationen finden Sie im Artikel Farbe und Bedienungshilfen in den Material-Richtlinien.

Geben Sie in app.dart unter inputDecorationTheme: eine focusedBorder: an :

// TODO: Decorate the inputs (103)
inputDecorationTheme: const InputDecorationTheme(
  border: OutlineInputBorder(),
  focusedBorder: OutlineInputBorder(
    borderSide: BorderSide(
      width: 2.0,
      color: kShrineBrown900,
    ),
  ),
),

Geben Sie als Nächstes unter inputDecorationTheme: einen floatingLabelStyle: an :

// TODO: Decorate the inputs (103)
inputDecorationTheme: const InputDecorationTheme(
  border: OutlineInputBorder(),
  focusedBorder: OutlineInputBorder(
    borderSide: BorderSide(
      width: 2.0,
      color: kShrineBrown900,
    ),
  ),
  floatingLabelStyle: TextStyle(
    color: kShrineBrown900,
  ),
),

Schließlich soll die Schaltfläche „Abbrechen“ zur Erhöhung des Kontrasts die sekundäre statt der primären Farbe verwenden.

TextButton(
  child: const Text('CANCEL'),
  onPressed: () {
    _usernameController.clear();
    _passwordController.clear();
  },
  style: TextButton.styleFrom(
    primary: Theme.of(context).colorScheme.secondary,
  ),
),

Projekt speichern.

Android

iOS

Anmeldeseite für Shrine mit zugänglicher Schaltfläche „ABBRECHEN“

Anmeldeseite für Shrine mit zugänglicher Schaltfläche „ABBRECHEN“

6. Höhe anpassen

Nachdem Sie die Seite mit einer bestimmten Farbe und Typografie gestaltet haben, die zu Shrine passt, passen wir die Erhebung an.

Erhebung der Schaltfläche „WEITER“ ändern

Die Standarderhebung für ein ElevatedButton ist 2. Wir können sie noch höher ansetzen.

Fügen Sie in login.dart dem ElevatedButton NEXT einen style:-Wert hinzu:

ElevatedButton(
  child: const Text('NEXT'),
  onPressed: () {
    Navigator.pop(context);
  },
  style: ElevatedButton.styleFrom(
    foregroundColor: kShrineBrown900,
    backgroundColor: kShrinePink100,
    elevation: 8.0,
  ),
),

Projekt speichern.

Android

iOS

Anmeldeseite für Shrine mit hervorgehobenem Button „WEITER“

Anmeldeseite für Shrine mit hervorgehobenem Button „WEITER“

Kartenhöhe anpassen

Derzeit werden die Karten auf einer weißen Fläche neben der Navigation der Website angezeigt.

Fügen Sie in home.dart den Wert elevation: zu den Karten hinzu:

// TODO: Adjust card heights (103)
elevation: 0.0,

Speichern Sie das Projekt.

Android

iOS

Produktübersichtsseite für Shrine ohne Erhebung für die einzelnen Karten

Produktübersichtsseite für Shrine ohne Erhebung für die einzelnen Karten

Der Schatten unter den Karten wurde entfernt.

7. Form hinzufügen

Das Shrine-Design hat einen coolen geometrischen Stil, bei dem Elemente mit einer achteckigen oder rechteckigen Form definiert werden. Wir implementieren das Formstyling in den Karten auf dem Startbildschirm sowie in den Textfeldern und Schaltflächen auf dem Anmeldebildschirm.

Formen der Textfelder auf dem Anmeldebildschirm ändern

Importieren Sie in app.dart die folgende Datei:

import 'supplemental/cut_corners_border.dart';

Ändern Sie in app.dart das Design der Textfelddekoration, um einen Rahmen mit abgeschnittenen Ecken zu verwenden:

// TODO: Decorate the inputs (103)
inputDecorationTheme: const InputDecorationTheme(
  border: CutCornersBorder(),
  focusedBorder: CutCornersBorder(
    borderSide: BorderSide(
      width: 2.0,
      color: kShrineBrown900,
    ),
  ), 
  floatingLabelStyle: TextStyle(
    color: kShrineBrown900,
  ),
),

Schaltflächenformen auf dem Anmeldebildschirm ändern

Fügen Sie in login.dart der Schaltfläche ABBRECHEN einen abgeschrägten rechteckigen Rahmen hinzu:

TextButton(
  child: const Text('CANCEL'),
  onPressed: () {
    _usernameController.clear();
    _passwordController.clear();
  },
  style: TextButton.styleFrom(
    foregroundColor: kShrineBrown900,
    shape: const BeveledRectangleBorder(
      borderRadius: BorderRadius.all(Radius.circular(7.0)),
    ),
  ),
),

Die TextButton-Komponente hat keine sichtbare Form. Warum sollte also eine Rahmenform hinzugefügt werden? Die Rippelanimation ist also an dieselbe Form gebunden, wenn sie berührt wird.

Fügen Sie nun die gleiche Form der Schaltfläche „WEITER“ hinzu:

ElevatedButton(
  child: const Text('NEXT'),
  onPressed: () {
    Navigator.pop(context);
  },
  style: ElevatedButton.styleFrom(
    foregroundColor: kShrineBrown900,
    backgroundColor: kShrinePink100,
    elevation: 8.0,
    shape: const BeveledRectangleBorder(
      borderRadius: BorderRadius.all(Radius.circular(7.0)),
    ),
  ),
),

Wenn wir die Form aller Schaltflächen ändern möchten, können wir auch elevatedButtonTheme oder textButtonTheme in app.dart verwenden. Das bleibt dem Lernenden als Herausforderung überlassen.

Heißstart.

Android

iOS

Anmeldeseite für den Schrein mit angewendetem Formdesign

Anmeldeseite für den Schrein mit angewendetem Formdesign

8. Layout ändern

Als Nächstes ändern wir das Layout, damit die Karten unterschiedliche Seitenverhältnisse und Größen haben und sich voneinander unterscheiden.

GridView durch AsymmetricView ersetzen

Wir haben die Dateien für ein asymmetrisches Layout bereits geschrieben.

Fügen Sie in home.dart den folgenden Import hinzu:

import 'supplemental/asymmetric_view.dart';

Löschen Sie _buildGridCards und ersetzen Sie body:

body: AsymmetricView(
  products: ProductsRepository.loadProducts(Category.all),
),

Speichern Sie das Projekt.

Android

iOS

Shrine-Produktseite mit asymmetrischem, horizontal scrollbarem Layout

Shrine-Produktseite mit asymmetrischem, horizontal scrollbarem Layout

Die Produkte werden jetzt horizontal in einem gewebten Muster gescrollt.

9. Anderes Design ausprobieren (optional)

Farbe ist ein wirkungsvolles Mittel, um Ihre Marke zu präsentieren. Eine kleine Farbänderung kann sich stark auf die User Experience auswirken. Sehen wir uns an, wie Shrine aussieht, wenn das Farbschema der Marke etwas anders wäre.

Farben ändern

Fügen Sie in colors.dart die folgende Farbe hinzu:

const kShrinePurple = Color(0xFF5D1049);

Ändern Sie in app.dart die Funktion _buildShrineTheme() so:

ThemeData _buildShrineTheme() {
  final ThemeData base = ThemeData.light();
  return base.copyWith(
    colorScheme: base.colorScheme.copyWith(
      primary: kShrinePurple,
      secondary: kShrinePurple,
      error: kShrineErrorRed,
    ),
    scaffoldBackgroundColor: kShrineSurfaceWhite,
    textSelectionTheme: const TextSelectionThemeData(
      selectionColor: kShrinePurple,
    ),
    appBarTheme: const AppBarTheme(
      foregroundColor: kShrineBrown900,
      backgroundColor: kShrinePink100,
    ),

    inputDecorationTheme: const InputDecorationTheme(
      border: CutCornersBorder(),
      focusedBorder: CutCornersBorder(
        borderSide: BorderSide(
          width: 2.0,
          color: kShrinePurple,
        ),
      ),
      floatingLabelStyle: TextStyle(
        color: kShrinePurple,
      ),
    ),
  );
}

Heißstart. Das neue Design sollte jetzt angezeigt werden.

Android

iOS

Anmeldeseite für den Schrein mit lila und rosa Design

Anmeldeseite für den Schrein mit lila und rosa Design

Android

iOS

Produktseite für einen Schrein mit rosa Design

Produktseite für einen Schrein mit rosa Design

Das Ergebnis ist sehr unterschiedlich. Lass uns app.dart's _buildShrineTheme auf den Zustand vor diesem Schritt zurücksetzen. Oder laden Sie den Startcode von 104 herunter.

10. Glückwunsch!

Sie haben jetzt eine App erstellt, die den Designvorgaben Ihres Designers entspricht.

Weiteres Vorgehen

Sie haben jetzt die folgenden Material Flutter-Elemente verwendet: Design, Typografie, Erhebung und Form. Weitere Komponenten und Subsysteme finden Sie in der Material-Flutter-Bibliothek.

Sehen Sie sich die Dateien im Verzeichnis supplemental an, um zu erfahren, wie wir das asymmetrische Layoutraster mit horizontalem Scrollen erstellt haben.

Was ist, wenn das geplante App-Design Elemente enthält, für die es keine Komponenten in der Bibliothek gibt? Im Codelab MDC-104: Material Advanced Components wird gezeigt, wie Sie benutzerdefinierte Komponenten mit der Material-Flutter-Bibliothek erstellen, um ein gewünschtes Aussehen zu erzielen.

Ich konnte dieses Codelab in angemessener Zeit und mit angemessenem Aufwand durcharbeiten.

Stimme vollkommen zu Stimme zu Neutral Stimme nicht zu Stimme überhaupt nicht zu

Ich möchte Material Components auch in Zukunft verwenden.

Stimme voll und ganz zu Stimme zu Neutral Stimme nicht zu Stimme überhaupt nicht zu