1. Introduzione
| I componenti Material (MDC) aiutano gli sviluppatori a implementare Material Design. Creato da un team di ingegneri e progettisti UX di Google, MDC include decine di componenti UI belli e funzionali ed è disponibile per Android, iOS, web e Flutter.material.io/develop |
Ora puoi utilizzare Material Flutter per personalizzare lo stile distintivo delle tue app più che mai. La recente espansione di Material Design offre a designer e sviluppatori una maggiore flessibilità per esprimere il brand del proprio prodotto.
Nei codelab MDC-101 e MDC-102,hai utilizzato Material Flutter per creare le basi di un'app chiamata Shrine, un'app di e-commerce che vende abbigliamento e articoli per la casa. Questa app contiene un flusso utente che inizia con una schermata di accesso, quindi porta l'utente a una schermata Home che mostra i prodotti.
Cosa creerai
In questo codelab, personalizzerai l'app Shrine utilizzando:
- Colore
- Tipografia
- Elevazione
- Forma
- Layout
Android | iOS |
|
|
|
|
Componenti e sottosistemi Material Flutter in questo codelab
- Temi
- Tipografia
- Elevazione
- Elenco immagini
Come valuteresti il tuo livello di esperienza con lo sviluppo Flutter?
2. Configura l'ambiente di sviluppo Flutter
Per completare questo lab, hai bisogno di due software: l'SDK Flutter e un editor.
Puoi eseguire il codelab utilizzando uno qualsiasi 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 (Chrome è necessario per il debug).
- Come applicazione desktop Windows, Linux o macOS. Devi sviluppare sulla piattaforma in cui prevedi di eseguire il deployment. Pertanto, se vuoi sviluppare un'app desktop Windows, devi svilupparla su Windows per accedere alla catena di build appropriata. Esistono requisiti specifici del sistema operativo trattati in dettaglio su docs.flutter.dev/desktop.
3. Scarica l'app iniziale del codelab
Hai seguito il corso MDC-102?
Se hai completato MDC-102, il codice dovrebbe essere pronto per questo codelab. Vai al passaggio: Modificare i colori.
Partire da zero?
Scarica l'app codelab iniziale
L'app iniziale si trova nella directory material-components-flutter-codelabs-103-starter_and_102-complete/mdc_100_series.
...o clonalo 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 103-starter_and_102-complete
Apri il progetto ed esegui l'app
- Apri il progetto nell'editor che preferisci.
- Segui le istruzioni per "Eseguire l'app" nella sezione Guida rapida: prova per l'editor che hai scelto.
Operazione riuscita. Sul dispositivo dovrebbe essere visualizzata la pagina di accesso di Shrine delle codelab precedenti.
Android | iOS |
|
|
Fai clic su "Avanti" per visualizzare la pagina del prodotto.
Android | iOS |
|
|
4. Cambiare i colori
È stata creata una combinazione di colori che rappresenta il brand Shrine e il designer vorrebbe che tu la implementassi nell'app Shrine
Per iniziare, importiamo questi colori nel nostro progetto.
Crea colors.dart
Crea un nuovo file Dart in lib denominato colors.dart. Importa material.dart e aggiungi i valori const Color:
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;
Tavolozza dei colori personalizzata
Questo tema di colori è stato creato da un designer con colori personalizzati (mostrati nell'immagine di seguito). Contiene colori selezionati dal brand di Shrine e applicati a Material Theme Editor, che li ha espansi per creare una tavolozza più completa. Questi colori non provengono dalle tavolozze dei colori Material del 2014.
L'editor del tema Material li ha organizzati in tonalità etichettate numericamente, incluse le etichette 50, 100, 200, ... fino a 900 di ogni colore. Shrine utilizza solo le tonalità 50, 100 e 300 del campione rosa e 900 del campione marrone.

Ogni parametro colorato di un widget viene mappato a un colore di questi schemi. Ad esempio, il colore delle decorazioni di un campo di testo quando riceve attivamente input deve essere il colore principale del tema. Se il colore non è accessibile (facile da vedere sullo sfondo), utilizza un altro colore.
Ora che abbiamo i colori che vogliamo utilizzare, possiamo applicarli all'interfaccia utente. Lo faremo impostando i valori di un widget ThemeData che applichiamo all'istanza MaterialApp nella parte superiore della gerarchia dei widget.
Personalizza ThemeData.light()
Flutter include alcuni temi integrati. Il tema chiaro è uno di questi. Anziché creare un widget ThemeData da zero, copieremo il tema chiaro e modificheremo i valori per personalizzarli per la nostra app.
Importiamo colors.dart in app.dart.
import 'colors.dart';
Quindi aggiungi quanto segue ad app.dart al di fuori dell'ambito della classe ShrineApp:
// 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)
);
}
Ora, imposta theme: alla fine della funzione build() di ShrineApp (nel widget MaterialApp) in modo che sia il nostro nuovo tema:
// TODO: Customize the theme (103)
theme: _kShrineTheme, // New code
Salvare il progetto. La schermata di accesso dovrebbe avere ora il seguente aspetto:
Android | iOS |
|
|
5. Modificare gli stili di tipografia ed etichette
Oltre alle modifiche del colore, il designer ci ha anche fornito una tipografia specifica da utilizzare. ThemeData di Flutter include tre temi di testo. Ogni tema di testo è una raccolta di stili di testo, come "titolo" e "intestazione". Utilizzeremo alcuni stili per la nostra app e modificheremo alcuni valori.
Personalizzare il tema del testo
Per importare i caratteri nel progetto, devono essere aggiunti al file pubspec.yaml.
In pubspec.yaml, aggiungi quanto segue subito dopo il tag flutter::
# TODO: Insert Fonts (103)
fonts:
- family: Rubik
fonts:
- asset: fonts/Rubik-Regular.ttf
- asset: fonts/Rubik-Medium.ttf
weight: 500
Ora puoi accedere al carattere Rubik e utilizzarlo.
Risoluzione dei problemi relativi al file pubspec
Potresti riscontrare errori durante l'esecuzione di pub get se tagli e incolli la dichiarazione riportata sopra. Se ricevi errori, inizia rimuovendo gli spazi bianchi iniziali e sostituendoli con spazi utilizzando un rientro di due spazi. (Due spazi prima
fonts:
, quattro spazi prima
family: Rubik
, e così via).
Se viene visualizzato il messaggio La mappatura dei valori non è consentita qui, controlla il rientro della riga che presenta il problema e di quelle sopra.
In login.dart, modifica quanto segue all'interno di Column():
Column(
children: <Widget>[
Image.asset('assets/diamond.png'),
const SizedBox(height: 16.0),
Text(
'SHRINE',
style: Theme.of(context).textTheme.headlineSmall,
),
],
)
In app.dart, aggiungi quanto segue dopo _buildShrineTheme():
// 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,
);
}
Prende un TextTheme e modifica l'aspetto di titoli, sottotitoli e didascalie.
L'applicazione di fontFamily in questo modo applica le modifiche solo ai valori della scala tipografica specificati in copyWith() (titolo, titolo, didascalia).
Per alcuni caratteri, impostiamo un fontWeight personalizzato, con incrementi di 100: w500 (il peso 500) corrisponde a medio e w400 a normale.
Utilizzare i nuovi temi
Aggiungi i seguenti temi a _buildShrineTheme dopo l'errore:
// TODO: Add the text themes (103)
textTheme: _buildShrineTextTheme(base.textTheme),
textSelectionTheme: const TextSelectionThemeData(
selectionColor: kShrinePink100,
),
Salvare il progetto. Questa volta, riavvia anche l'app (operazione nota come Riavvio rapido), poiché abbiamo modificato i caratteri.
Android | iOS |
|
|
Il testo nelle schermate di accesso e Home ha un aspetto diverso: alcuni testi utilizzano il carattere Rubik, mentre altri vengono visualizzati in marrone anziché in nero o bianco. Anche le icone vengono visualizzate in marrone.
Ridurre il testo
Le etichette sono troppo grandi.
In home.dart, modifica children: della colonna più interna:
// 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
],
Centrare e rilasciare il testo
Vogliamo centrare le etichette e allineare il testo alla parte inferiore di ogni scheda, anziché alla parte inferiore di ogni immagine.
Sposta le etichette alla fine (in basso) dell'asse principale e centrarle:
// TODO: Align labels to the bottom and center (103)
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.center,
Salvare il progetto.
Android | iOS |
|
|
Ora va molto meglio.
Applicare un tema ai campi di testo
Puoi anche applicare un tema alla decorazione dei campi di testo con un InputDecorationTheme.
In app.dart, nel metodo _buildShrineTheme(), specifica un valore inputDecorationTheme::
// TODO: Decorate the inputs (103)
inputDecorationTheme: const InputDecorationTheme(
border: OutlineInputBorder(),
),
Al momento, i campi di testo hanno una decorazione filled. Rimuoviamolo. Se rimuovi filled e specifichi inputDecorationTheme, i campi di testo avranno lo stile del contorno.
In login.dart, rimuovi i valori filled: true:
// 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,
),
Riavvio a caldo. La schermata di accesso dovrebbe essere simile a questa quando il campo Nome utente è attivo (quando stai digitando):
Android | iOS |
|
|
Digita in un campo di testo: i bordi e le etichette mobili vengono visualizzati nel colore principale. ma non è facile vederlo. Non è accessibile alle persone che hanno difficoltà a distinguere i pixel che non hanno un contrasto cromatico sufficiente. Per saperne di più, consulta l'articolo su colore e accessibilità delle linee guida di Material Design.
In app.dart, specifica un focusedBorder: in inputDecorationTheme: :
// TODO: Decorate the inputs (103)
inputDecorationTheme: const InputDecorationTheme(
border: OutlineInputBorder(),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
width: 2.0,
color: kShrineBrown900,
),
),
),
Successivamente, specifica un floatingLabelStyle: in inputDecorationTheme: :
// TODO: Decorate the inputs (103)
inputDecorationTheme: const InputDecorationTheme(
border: OutlineInputBorder(),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
width: 2.0,
color: kShrineBrown900,
),
),
floatingLabelStyle: TextStyle(
color: kShrineBrown900,
),
),
Infine, facciamo in modo che il pulsante Annulla utilizzi il colore secondario anziché quello principale per aumentare il contrasto.
TextButton(
child: const Text('CANCEL'),
onPressed: () {
_usernameController.clear();
_passwordController.clear();
},
style: TextButton.styleFrom(
primary: Theme.of(context).colorScheme.secondary,
),
),
Salvare il progetto.
Android | iOS |
|
|
6. Regolare l'elevazione
Ora che hai applicato uno stile alla pagina con colori e tipografia specifici che corrispondono a Shrine, regoliamo l'elevazione.
Modificare l'elevazione del pulsante AVANTI
L'elevazione predefinita per un ElevatedButton è 2. Alziamolo ancora un po'.
In login.dart, aggiungi un valore style: all'ElevatedButton AVANTI:
ElevatedButton(
child: const Text('NEXT'),
onPressed: () {
Navigator.pop(context);
},
style: ElevatedButton.styleFrom(
foregroundColor: kShrineBrown900,
backgroundColor: kShrinePink100,
elevation: 8.0,
),
),
Salvare il progetto.
Android | iOS |
|
|
Regolare l'elevazione della scheda
Al momento, le schede si trovano su una superficie bianca accanto alla navigazione del sito.
In home.dart, aggiungi un valore elevation: a Carte:
// TODO: Adjust card heights (103)
elevation: 0.0,
Salva il progetto.
Android | iOS |
|
|
Hai rimosso l'ombra sotto le carte.
7. Aggiungi forma
Il santuario ha uno stile geometrico interessante, che definisce gli elementi con una forma ottagonale o rettangolare. Implementiamo lo stile della forma nelle schede della schermata Home e nei campi di testo e nei pulsanti della schermata di accesso.
Modificare le forme dei campi di testo nella schermata di accesso
In app.dart, importa il seguente file:
import 'supplemental/cut_corners_border.dart';
Sempre in app.dart, modifica il tema di decorazione del campo di testo in modo che utilizzi un bordo con angoli smussati:
// TODO: Decorate the inputs (103)
inputDecorationTheme: const InputDecorationTheme(
border: CutCornersBorder(),
focusedBorder: CutCornersBorder(
borderSide: BorderSide(
width: 2.0,
color: kShrineBrown900,
),
),
floatingLabelStyle: TextStyle(
color: kShrineBrown900,
),
),
Modificare le forme dei pulsanti nella schermata di accesso
In login.dart, aggiungi un bordo rettangolare smussato al pulsante ANNULLA:
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)),
),
),
),
TextButton non ha una forma visibile, quindi perché aggiungere una forma del bordo? Pertanto, l'animazione a increspatura è associata alla stessa forma quando viene toccata.
Ora aggiungi la stessa forma al pulsante AVANTI:
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)),
),
),
),
Per modificare la forma di tutti i pulsanti, possiamo utilizzare anche elevatedButtonTheme o textButtonTheme in app.dart. Lasciamo questa sfida allo studente.
Riavvio a caldo.
Android | iOS |
|
|
8. Modificare il layout
Successivamente, modifichiamo il layout per mostrare le schede con proporzioni e dimensioni diverse, in modo che ogni scheda sia diversa dalle altre.
Sostituisci GridView con AsymmetricView
Abbiamo già scritto i file per un layout asimmetrico.
In home.dart, aggiungi la seguente importazione:
import 'supplemental/asymmetric_view.dart';
Elimina _buildGridCards e sostituisci body:
body: AsymmetricView(
products: ProductsRepository.loadProducts(Category.all),
),
Salva il progetto.
Android | iOS |
|
|
Ora i prodotti scorrono orizzontalmente in un motivo ispirato a una trama.
9. Prova un altro tema (facoltativo)
Il colore è un modo efficace per esprimere il tuo brand e un piccolo cambiamento di colore può avere un grande effetto sull'esperienza utente. Per fare una prova, vediamo come appare Shrine se la combinazione di colori del brand fosse leggermente diversa.
Modificare i colori
In colors.dart, aggiungi il seguente colore:
const kShrinePurple = Color(0xFF5D1049);
In app.dart, modifica la funzione _buildShrineTheme() nel seguente modo:
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,
),
),
);
}
Riavvio a caldo. Ora dovrebbe essere visualizzato il nuovo tema.
Android | iOS |
|
|
Android | iOS |
|
|
Il risultato è molto diverso. Ripristiniamo app.dart's _buildShrineTheme allo stato precedente a questo passaggio. In alternativa, scarica il codice di avvio di 104.
10. Complimenti!
A questo punto, hai creato un'app che rispecchia le specifiche di progettazione del tuo designer.
Passaggi successivi
Ora hai utilizzato i seguenti elementi di Material Flutter: tema, tipografia, elevazione e forma. Puoi esplorare altri componenti e sottosistemi nella libreria Material Flutter.
Esplora i file nella directory supplemental per scoprire come abbiamo creato la griglia di layout asimmetrica a scorrimento orizzontale.
Cosa succede se il design dell'app che hai pianificato contiene elementi che non hanno componenti nella libreria? In MDC-104: Material Advanced Components mostriamo come creare componenti personalizzati utilizzando la libreria Material Flutter per ottenere l'aspetto desiderato.


























