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 |
Im Codelab MDC-101 haben Sie zwei Material-Komponenten verwendet, um eine Anmeldeseite zu erstellen: Textfelder und Schaltflächen mit Tintenwellen. Jetzt wollen wir diese Grundlage erweitern, indem wir Navigation, Struktur und Daten hinzufügen.
Umfang
In diesem Codelab erstellen Sie einen Startbildschirm für eine App namens Shrine, eine E-Commerce-App, in der Kleidung und Haushaltswaren verkauft werden. Sie enthält:
- Eine obere App-Leiste
- Eine Rasterliste mit Produkten
Android | iOS |
|
|
Material-Flutter-Komponenten und ‑Subsysteme in diesem Codelab
- Obere App-Leiste
- Raster
- Karten
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 machen mit MDC-101 weiter?
Wenn Sie MDC-101 abgeschlossen haben, sollte Ihr Code für dieses Codelab vorbereitet sein. Direkt zum Schritt „Obere App-Leiste hinzufügen“
Sie fangen bei null an?
Starter-App für das Codelab herunterladen
Die Starter-App befindet sich im Verzeichnis material-components-flutter-codelabs-102-starter_and_101-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 102-starter_and_101-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 dem MDC-101-Codelab angezeigt werden.
Android | iOS |
|
|
Nachdem der Anmeldebildschirm gut aussieht, füllen wir die App mit einigen Produkten.
4. Obere App-Leiste hinzufügen
Wenn Sie jetzt auf die Schaltfläche „Weiter“ klicken, wird der Startbildschirm mit der Meldung „Du hast es geschafft!“ angezeigt. Sehr gut. Der Nutzer kann jetzt aber keine Aktionen ausführen und weiß auch nicht, wo er sich in der App befindet. Um ihm zu helfen, müssen wir die Navigation hinzufügen.
Material Design bietet Navigationsmuster, die für eine hohe Benutzerfreundlichkeit sorgen. Eine der sichtbarsten Komponenten ist die obere App-Leiste.
Um die Navigation zu ermöglichen und Nutzern schnellen Zugriff auf andere Aktionen zu geben, fügen wir eine obere App-Leiste hinzu.
AppBar-Widget hinzufügen
Fügen Sie in home.dart eine AppBar zum Scaffold hinzu und entfernen Sie die hervorgehobene const:
return const Scaffold(
// TODO: Add app bar (102)
appBar: AppBar(
// TODO: Add buttons and title (102)
),
Wenn wir die AppBar dem appBar:-Feld des Scaffold hinzufügen, erhalten wir ein perfektes Layout, bei dem die AppBar oben auf der Seite und der Body darunter platziert werden.
Textwidget hinzufügen
Fügen Sie in home.dart einen Titel für die AppBar hinzu:
// TODO: Add app bar (102)
appBar: AppBar(
// TODO: Add buttons and title (102)
title: const Text('SHRINE'),
// TODO: Add trailing buttons (102)
Projekt speichern.
Android | iOS |
|
|
Viele App-Leisten haben eine Schaltfläche neben dem Titel. Fügen wir unserer App ein Menüsymbol hinzu.
Führendes IconButton hinzufügen
Legen Sie in home.dart für das Feld leading: der AppBar ein IconButton fest. (Fügen Sie es vor dem Feld title: ein, um die Reihenfolge von führend nach nachfolgend zu simulieren):
// TODO: Add buttons and title (102)
leading: IconButton(
icon: const Icon(
Icons.menu,
semanticLabel: 'menu',
),
onPressed: () {
print('Menu button');
},
),
Projekt speichern.
Android | iOS |
|
|
Das Menüsymbol (auch als „Hamburger“ bezeichnet) wird an der erwarteten Stelle angezeigt.
Sie können auch Schaltflächen auf der rechten Seite des Titels hinzufügen. In Flutter werden diese als „Aktionen“ bezeichnet.
Aktionen hinzufügen
Es ist noch Platz für zwei weitere IconButtons.
Fügen Sie sie nach dem Titel der AppBar-Instanz hinzu:
// TODO: Add trailing buttons (102)
actions: <Widget>[
IconButton(
icon: const Icon(
Icons.search,
semanticLabel: 'search',
),
onPressed: () {
print('Search button');
},
),
IconButton(
icon: const Icon(
Icons.tune,
semanticLabel: 'filter',
),
onPressed: () {
print('Filter button');
},
),
],
Projekt speichern. Ihr Startbildschirm sollte so aussehen:
Android | iOS |
|
|
Die App hat jetzt eine führende Schaltfläche, einen Titel und zwei Aktionen auf der rechten Seite. In der App-Leiste wird auch die Erhebung durch einen dezenten Schatten dargestellt, der zeigt, dass sie sich auf einer anderen Ebene als die Inhalte befindet.
5. Karte in einem Raster hinzufügen
Nachdem wir unserer App eine Struktur gegeben haben, organisieren wir die Inhalte, indem wir sie in Karten platzieren.
GridView hinzufügen
Fügen wir zuerst eine Karte unter der oberen App-Leiste hinzu. Das Card-Widget allein enthält nicht genügend Informationen, um sich so zu positionieren, dass es sichtbar ist. Daher müssen wir es in ein GridView-Widget einbetten.
Ersetzen Sie das Center im Body des Scaffolds durch ein GridView:
// TODO: Add a grid view (102)
body: GridView.count(
crossAxisCount: 2,
padding: const EdgeInsets.all(16.0),
childAspectRatio: 8.0 / 9.0,
// TODO: Build a grid of cards (102)
children: <Widget>[Card()],
),
Sehen wir uns den Code genauer an. GridView ruft den count()-Konstruktor auf, da die Anzahl der angezeigten Elemente zählbar und nicht unendlich ist. Für das Layout sind jedoch weitere Informationen erforderlich.
Der Parameter crossAxisCount: gibt an, wie viele Elemente nebeneinander angezeigt werden. Wir möchten zwei Spalten.
Das Feld padding: bietet Platz auf allen vier Seiten des GridView. Das Padding auf der nachfolgenden oder unteren Seite ist natürlich nicht zu sehen, da sich daneben noch keine GridView-Untergeordneten befinden.
Das Feld childAspectRatio: gibt die Größe der Elemente basierend auf einem Seitenverhältnis (Breite über Höhe) an.
Standardmäßig werden in GridView Kacheln mit derselben Größe erstellt.
Wir haben eine Karte, aber sie ist leer. Fügen wir der Karte nun untergeordnete Widgets hinzu.
Inhalte anordnen
Infokarten sollten Bereiche für ein Bild, einen Titel und sekundären Text haben.
Aktualisieren Sie die untergeordneten Elemente von GridView:
// TODO: Build a grid of cards (102)
children: <Widget>[
Card(
clipBehavior: Clip.antiAlias,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
AspectRatio(
aspectRatio: 18.0 / 11.0,
child: Image.asset('assets/diamond.png'),
),
Padding(
padding: const EdgeInsets.fromLTRB(16.0, 12.0, 16.0, 8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('Title'),
const SizedBox(height: 8.0),
Text('Secondary Text'),
],
),
),
],
),
)
],
Mit diesem Code wird ein Column-Widget hinzugefügt, mit dem die untergeordneten Widgets vertikal angeordnet werden.
Mit crossAxisAlignment: field wird CrossAxisAlignment.start angegeben, was bedeutet, dass der Text am linken Rand ausgerichtet wird.
Das AspectRatio-Widget bestimmt die Form des Bildes, unabhängig davon, welche Art von Bild bereitgestellt wird.
Mit Padding wird der Text etwas von der Seite eingerückt.
Die beiden Text-Widgets sind vertikal gestapelt und haben einen Abstand von 8 Punkten (SizedBox). Wir erstellen eine weitere Spalte, um sie im Padding unterzubringen.
Projekt speichern.
Android | iOS |
|
|
In dieser Vorschau ist die Karte vom Rand eingerückt, hat abgerundete Ecken und einen Schatten, der die Höhe der Karte angibt. Die gesamte Form wird in Material als „Container“ bezeichnet. Nicht zu verwechseln mit der eigentlichen Widget-Klasse Container.
Karten werden normalerweise in einer Sammlung mit anderen Karten angezeigt. Wir können sie als Sammlung in einem Raster anordnen.
6. Kartensammlung erstellen
Wenn auf einem Bildschirm mehrere Karten vorhanden sind, werden sie in einer oder mehreren Sammlungen gruppiert. Die Karten in einer Sammlung sind koplanar, d. h., sie haben alle dieselbe Höhe (es sei denn, sie werden aufgenommen oder gezogen, was hier aber nicht der Fall ist).
Karte in eine Sammlung einfügen
Derzeit wird unsere Karte inline mit dem Feld children: der GridView erstellt. Das ist viel verschachtelter Code, der schwer zu lesen sein kann. Wir extrahieren sie in eine Funktion, die beliebig viele leere Karten generieren und eine Liste mit Karten zurückgeben kann.
Erstellen Sie eine neue private Funktion über der Funktion build(). Denken Sie daran, dass Funktionen, die mit einem Unterstrich beginnen, private APIs sind:
// TODO: Make a collection of cards (102)
List<Card> _buildGridCards(int count) {
List<Card> cards = List.generate(
count,
(int index) {
return Card(
clipBehavior: Clip.antiAlias,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
AspectRatio(
aspectRatio: 18.0 / 11.0,
child: Image.asset('assets/diamond.png'),
),
Padding(
padding: const EdgeInsets.fromLTRB(16.0, 12.0, 16.0, 8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: const <Widget>[
Text('Title'),
SizedBox(height: 8.0),
Text('Secondary Text'),
],
),
),
],
),
);
},
);
return cards;
}
Weisen Sie die generierten Karten dem Feld children von GridView zu. Ersetzen Sie alles, was in der GridView enthalten ist, durch diesen neuen Code:
// TODO: Add a grid view (102)
body: GridView.count(
crossAxisCount: 2,
padding: const EdgeInsets.all(16.0),
childAspectRatio: 8.0 / 9.0,
children: _buildGridCards(10) // Replace
),
Projekt speichern.
Android | iOS |
|
|
Die Karten sind vorhanden, aber es wird noch nichts angezeigt. Jetzt ist es an der Zeit, Produktdaten hinzuzufügen.
Produktdaten hinzufügen
Die App enthält einige Produkte mit Bildern, Namen und Preisen. Fügen wir das den Widgets hinzu, die wir bereits auf der Karte haben.
Importieren Sie dann in home.dart ein neues Paket und einige Dateien, die wir für ein Datenmodell bereitgestellt haben:
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'model/product.dart';
import 'model/products_repository.dart';
Ändern Sie schließlich _buildGridCards(), um die Produktinformationen abzurufen, und verwenden Sie diese Daten in den Karten:
// TODO: Make a collection of cards (102)
// Replace this entire method
List<Card> _buildGridCards(BuildContext context) {
List<Product> products = ProductsRepository.loadProducts(Category.all);
if (products.isEmpty) {
return const <Card>[];
}
final ThemeData theme = Theme.of(context);
final NumberFormat formatter = NumberFormat.simpleCurrency(
locale: Localizations.localeOf(context).toString());
return products.map((product) {
return Card(
clipBehavior: Clip.antiAlias,
// TODO: Adjust card heights (103)
child: Column(
// TODO: Center items on the card (103)
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
AspectRatio(
aspectRatio: 18 / 11,
child: Image.asset(
product.assetName,
package: product.assetPackage,
// TODO: Adjust the box size (102)
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.fromLTRB(16.0, 12.0, 16.0, 8.0),
child: Column(
// TODO: Align labels to the bottom and center (103)
crossAxisAlignment: CrossAxisAlignment.start,
// TODO: Change innermost Column (103)
children: <Widget>[
// TODO: Handle overflowing labels (103)
Text(
product.name,
style: theme.textTheme.titleLarge,
maxLines: 1,
),
const SizedBox(height: 8.0),
Text(
formatter.format(product.price),
style: theme.textTheme.titleSmall,
),
],
),
),
),
],
),
);
}).toList();
}
HINWEIS:Der Code wird noch nicht kompiliert und ausgeführt. Wir haben noch eine Änderung.
Ändern Sie außerdem die Funktion build() so, dass der BuildContext an _buildGridCards() übergeben wird, bevor Sie versuchen, den Code zu kompilieren:
// TODO: Add a grid view (102)
body: GridView.count(
crossAxisCount: 2,
padding: const EdgeInsets.all(16.0),
childAspectRatio: 8.0 / 9.0,
children: _buildGridCards(context) // Changed code
),
Führe einen Hot Restart der App durch.
Android | iOS |
|
|
Wir fügen keinen vertikalen Abstand zwischen den Karten ein. Das liegt daran, dass sie standardmäßig oben und unten einen Rand von 4 Punkten haben.
Projekt speichern.
Die Produktdaten werden angezeigt, aber die Bilder haben zusätzlichen Leerraum. Die Bilder werden standardmäßig mit einem BoxFit von .scaleDown gezeichnet (in diesem Fall). Ändern wir das in .fitWidth, damit die Bilder etwas vergrößert und die zusätzlichen Leerzeichen entfernt werden.
Fügen Sie dem Bild das Feld fit: mit dem Wert BoxFit.fitWidth hinzu:
// TODO: Adjust the box size (102)
fit: BoxFit.fitWidth,
Android | iOS |
|
|
Unsere Produkte werden jetzt perfekt in der App angezeigt.
7. Glückwunsch!
Unsere App hat einen einfachen Ablauf, der den Nutzer vom Anmeldebildschirm zu einem Startbildschirm führt, auf dem Produkte angezeigt werden. Mit nur wenigen Codezeilen haben wir eine obere App-Leiste (mit einem Titel und drei Schaltflächen) und Karten (zur Präsentation der Inhalte unserer App) hinzugefügt. Unser Startbildschirm ist jetzt einfach und funktional, mit einer grundlegenden Struktur und umsetzbaren Inhalten.
Weiteres Vorgehen
Mit der oberen App-Leiste, der Karte, dem Textfeld und der Schaltfläche haben wir nun vier Kernkomponenten aus der Material-Flutter-Bibliothek verwendet. Weitere Informationen finden Sie im Katalog der Material-Komponenten-Widgets.
Sie ist zwar voll funktionsfähig, aber es wird noch keine bestimmte Marke oder Meinung vertreten. In MDC-103: Material Design Theming with Color, Shape, Elevation and Type (MDC-103: Material Design-Theming mit Farbe, Form, Höhe und Typ) passen wir den Stil dieser Komponenten an, um eine lebendige, moderne Marke zu präsentieren.
















