1. Introduzione
Material Components (MDC) aiutano gli sviluppatori a implementare Material Design. Creato da un team di ingegneri e designer UX di Google, MDC offre dozzine di componenti dell'interfaccia utente belli e funzionali ed è disponibile per Android, iOS, web e Flutter.material.io/develop |
Nel codelab MDC-101, hai utilizzato due componenti Material per creare una pagina di accesso: campi di testo e pulsanti con onde di inchiostro. Esaminiamo queste basi aggiungendo navigazione, struttura e dati.
Cosa creerai
In questo codelab, creerai la schermata Home di un'app chiamata Shrine, un'app di e-commerce che vende abbigliamento e articoli per la casa. Contiene:
- Una barra delle app in alto
- Un elenco a griglia pieno di prodotti
Android | iOS |
Componenti e sottosistemi di Material Flutter in questo codelab
- Barra delle app in alto
- Griglie
- Carte
Come valuteresti il tuo livello di esperienza nello sviluppo di Flutter?
2. Configurare l'ambiente di sviluppo Flutter
Per completare questo lab sono necessari due software: l'SDK Flutter e l'editor.
Puoi eseguire il codelab utilizzando uno di questi dispositivi:
- Un dispositivo fisico Android o iOS connesso al computer e impostato sulla modalità sviluppatore.
- Il simulatore iOS (richiede l'installazione degli strumenti Xcode).
- L'emulatore Android (richiede la configurazione in Android Studio).
- Un browser (per il debug è richiesto Chrome).
- Come applicazione desktop per Windows, Linux o macOS. Devi svilupparle sulla piattaforma in cui prevedi di eseguire il deployment. Quindi, se vuoi sviluppare un'app desktop per Windows, devi sviluppare su Windows per accedere alla catena di build appropriata. Esistono requisiti specifici per il sistema operativo che sono descritti in dettaglio su docs.flutter.dev/desktop.
3. Scarica l'app di avvio del codelab
Vuoi continuare da MDC-101?
Se hai completato MDC-101, il tuo codice dovrebbe essere preparato per questo codelab. Vai al passaggio Aggiungi una barra delle app in alto.
Vuoi iniziare da zero?
Scarica l'app codelab iniziale
L'app iniziale si trova nella directory material-components-flutter-codelabs-102-starter_and_101-complete/mdc_100_series
.
...o clonarlo da GitHub
Per clonare questo codelab da GitHub, esegui i seguenti comandi:
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
Apri il progetto ed esegui l'app
- Apri il progetto nel tuo editor preferito.
- Segui le istruzioni "Esegui l'app" in Inizia: prova per l'editor che hai scelto.
Operazione riuscita. Sul tuo dispositivo dovresti visualizzare la pagina di accesso a Santuario del codelab MDC-101.
Android | iOS |
Ora che la schermata di accesso è corretta, aggiungiamo alcuni prodotti all'app.
4. Aggiungere una barra delle app in alto
Al momento, se fai clic sul pulsante "Avanti", vedrai la schermata Home con la dicitura "Ce l'hai fatta!". Fantastico. Ora invece i nostri utenti non hanno azioni da intraprendere o hanno la sensazione di dove si trovano nell'app. Per aiutarci, è il momento di aggiungere le indicazioni di navigazione.
Material Design offre pattern di navigazione che garantiscono un elevato grado di usabilità. Uno dei componenti più visibili è una barra delle app in alto.
Per fornire la navigazione e consentire agli utenti di accedere rapidamente ad altre azioni, aggiungiamo una barra delle app in alto.
Aggiungere un widget AppBar
In home.dart
, aggiungi un'AppBar allo Scaffold e rimuovi la const
evidenziata:
return const Scaffold(
// TODO: Add app bar (102)
appBar: AppBar(
// TODO: Add buttons and title (102)
),
L'aggiunta di AppBar al campo appBar:
dello Scaffold ci permette di avere un layout senza costi perfetto, con l'AppBar nella parte superiore della pagina e il corpo sotto.
Aggiungi un widget Testo
In home.dart
, aggiungi un titolo all'AppBar:
// TODO: Add app bar (102)
appBar: AppBar(
// TODO: Add buttons and title (102)
title: const Text('SHRINE'),
// TODO: Add trailing buttons (102)
Salvare il progetto.
Android | iOS |
Molte barre delle app hanno un pulsante accanto al titolo. Aggiungiamo un'icona del menu nella nostra app.
Aggiungi un IconButton iniziale
Sempre in home.dart
, imposta un IconButton per il campo leading:
di AppBar. Inseriscilo prima del campo title:
per simulare l'ordine iniziale alla fine:
// TODO: Add buttons and title (102)
leading: IconButton(
icon: const Icon(
Icons.menu,
semanticLabel: 'menu',
),
onPressed: () {
print('Menu button');
},
),
Salvare il progetto.
Android | iOS |
L'icona del menu (nota anche come"menu a tre linee") viene visualizzata esattamente dove ti aspetti.
Puoi anche aggiungere pulsanti alla fine del titolo. In Flutter, queste sono chiamate "azioni".
Aggiungere azioni
C'è spazio per altri due pulsanti IconButton.
Aggiungili all'istanza AppBar dopo il titolo:
// 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');
},
),
],
Salvare il progetto. La schermata Home dovrebbe avere il seguente aspetto:
Android | iOS |
Ora l'app ha un pulsante iniziale, un titolo e due azioni sul lato destro. La barra delle app mostra anche l'elevazione utilizzando un'ombra sottile che indica che si trova su un livello diverso rispetto ai contenuti.
5. Aggiungere una scheda in una griglia
Ora che la nostra app ha una certa struttura, organizziamo i contenuti inserendoli nelle schede.
Aggiungi una griglia
Inizia aggiungendo una scheda sotto la barra delle app in alto. Il widget Scheda da solo non contiene informazioni sufficienti per essere visualizzato, quindi è necessario incapsularlo in un widget GridView.
Sostituisci il Centro nel corpo di Scaffold con una 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()],
),
Estraiamo il codice. GridView invoca il costruttore count()
poiché il numero di elementi visualizzati è conteggiabile e non infinito. ma ha bisogno di ulteriori informazioni per definirne il layout.
crossAxisCount:
specifica il numero di elementi. Vogliamo 2 colonne.
Il campo padding:
fornisce spazio su tutti e quattro i lati di GridView. Ovviamente non puoi vedere i margini sui lati di seguito o in basso perché non ci sono ancora elementi GridView accanto.
Il campo childAspectRatio:
identifica le dimensioni degli elementi in base alle proporzioni (larghezza rispetto all'altezza).
Per impostazione predefinita, GridView crea riquadri tutti delle stesse dimensioni.
Abbiamo una carta, ma è vuota. Aggiungiamo dei widget secondari alla nostra scheda.
Layout dei contenuti
Le schede devono avere regioni per un'immagine, un titolo e un testo secondario.
Aggiorna gli elementi secondari di 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'),
],
),
),
],
),
)
],
Questo codice aggiunge un widget Colonna utilizzato per disporre i widget secondari in verticale.
Il crossAxisAlignment: field
specifica CrossAxisAlignment.start
, che significa "allinea il testo al bordo iniziale".
Il widget AspectRatio decide la forma dell'immagine, indipendentemente dal tipo di immagine fornito.
Spaziatura interna avvicina un po' il testo lateralmente.
I due widget Testo sono impilzati verticalmente con uno spazio vuoto di 8 punti tra di loro (SizedBox). Creiamo un'altra colonna per inserirli all'interno del padding.
Salvare il progetto.
Android | iOS |
In questa anteprima, puoi vedere che la scheda è rientrata rispetto al bordo, con angoli arrotondati e un'ombra (che esprime l'elevazione della scheda). L'intera forma è chiamata "contenitore" in Material. Da non confondere con la classe di widget effettiva chiamata Container.
In genere le schede vengono mostrate in una raccolta insieme ad altre schede. Disponiamoli come una raccolta in una griglia.
6. Crea una raccolta di schede
Quando in una schermata sono presenti più schede, queste vengono raggruppate in una o più raccolte. Le schede di una raccolta sono coplanari, il che significa che condividono la stessa altezza di riposo (a meno che non vengano sollevate o trascinate, ma non lo faremo qui).
Moltiplicare la scheda in una raccolta
Al momento la nostra scheda è costruita in linea con il campo children:
di GridView. Si tratta di molto codice nidificato che può essere difficile da leggere. Estraiamolo in una funzione che possa generare tutte le schede vuote che vogliamo e restituisca un elenco di schede.
Crea una nuova funzione privata sopra la funzione build()
(ricorda che le funzioni che iniziano con il trattino basso sono API private):
// 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;
}
Assegna le schede generate al campo children
di GridView. Ricorda di sostituire tutto il contenuto di GridView con questo nuovo codice:
// 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
),
Salvare il progetto.
Android | iOS |
Le schede sono presenti, ma non mostrano ancora nulla. È il momento di aggiungere i dati di prodotto.
Aggiungere i dati di prodotto
L'app ha alcuni prodotti con immagini, nomi e prezzi. Aggiungiamolo ai widget già presenti nella scheda
Quindi, in home.dart
, importa un nuovo pacchetto e alcuni file forniti per un modello dei dati:
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'model/product.dart';
import 'model/products_repository.dart';
Infine, modifica _buildGridCards()
per recuperare le informazioni sul prodotto e utilizza questi dati nelle schede:
// 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();
}
NOTA:non verrà ancora compilata ed eseguita. C'è un'altra modifica.
Inoltre, modifica la funzione build()
per passare BuildContext a _buildGridCards()
prima di provare a compilare:
// 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
),
Riavvia l'app a caldo.
Android | iOS |
Potresti notare che non viene aggiunto alcuno spazio verticale tra le schede. Questo perché, per impostazione predefinita, sono presenti 4 punti di margine nella parte superiore e in quella inferiore.
Salvare il progetto.
I dati di prodotto vengono visualizzati, ma intorno alle immagini è presente uno spazio aggiuntivo. Le immagini vengono disegnate con un BoxFit di .scaleDown
per impostazione predefinita (in questo caso). Cambiamo con .fitWidth
per aumentare un po' lo zoom e rimuovere gli spazi bianchi extra.
Aggiungi un campo fit:
all'immagine con il valore BoxFit.fitWidth
:
// TODO: Adjust the box size (102)
fit: BoxFit.fitWidth,
Android | iOS |
I nostri prodotti ora vengono visualizzati perfettamente nell'app.
7. Complimenti!
La nostra app ha un flusso di base che indirizza l'utente dalla schermata di accesso a una schermata Home, dove è possibile visualizzare i prodotti. Con poche righe di codice, abbiamo aggiunto una barra dell'app superiore (con un titolo e tre pulsanti) e schede (per presentare i contenuti della nostra app). La nostra home page è ora semplice e funzionale, con una struttura di base e contenuti utili.
Passaggi successivi
Con la barra delle app in alto, la scheda, il campo di testo e il pulsante, abbiamo utilizzato quattro componenti di base della libreria Material Flutter. Per saperne di più, visita il catalogo dei widget dei componenti Material.
Sebbene sia completamente funzionante, la nostra app non esprime ancora un brand o un punto di vista specifico. In MDC-103: Material Design Theming with Color, Shape, Elevation and Type, personalizzeremo lo stile di questi componenti per esprimere un brand vivace e moderno.