1. Einführung
| 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 |
|
|
|
|
Material-Flutter-Komponenten und ‑Subsysteme in diesem Codelab
- Designs
- Typografie
- Höhe
- Bildliste
Wie würden Sie Ihre Erfahrung mit der Flutter-Entwicklung bewerten?
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
- Öffnen Sie das Projekt in einem beliebigen Editor.
- 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 |
|
|
Klicken Sie auf „Weiter“, um die Produktseite aufzurufen.
Android | iOS |
|
|
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.

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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
Android | iOS |
|
|
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.


























