1. Introduzione
Material Components (MDC) consente agli sviluppatori di implementare Material Design. Creato dal team di ingegneri e designer UX di Google, MDC è dotato di decine di componenti UI belli e funzionali ed è disponibile per Android, iOS, web e Flutter.material.io/develop |
Ora puoi usare Material Flutter per personalizzare le tue app e uno stile distintivo più che mai. La recente espansione di Material Design offre a designer e sviluppatori una maggiore flessibilità per esprimere il brand del 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, poi rimanda l'utente a una schermata Home in cui sono visualizzati i prodotti.
Cosa creerai
In questo codelab personalizzerai l'app Santuario utilizzando:
- Colore
- Tipografia
- Elevazione
- Shape
- Layout
Android | iOS |
Componenti e sottosistemi di Material Flutter in questo codelab
- Temi
- Tipografia
- Elevazione
- Elenco immagini
Come valuteresti il tuo livello di esperienza nello sviluppo di Flutter?
2. Configura l'ambiente di sviluppo di 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 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. Alcuni requisiti specifici del sistema operativo sono descritti in dettaglio all'indirizzo docs.flutter.dev/desktop.
3. Scarica l'app iniziale del codelab
Vuoi continuare da MDC-102?
Se hai completato MDC-102, il tuo codice dovrebbe essere pronto per questo codelab. Vai al passaggio Cambia colori.
Vuoi iniziare 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 clonarlo da GitHub
Per clonare questo codelab da GitHub, esegui questi 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 "Esegui l'app". in Inizia: prova l'editor che hai scelto.
Operazione riuscita. Sul tuo dispositivo dovresti visualizzare la pagina di accesso a Santuario dei 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 Santuario e il designer vorrebbe che lo implementi nell'app Santuario.
Per iniziare, importa quei colori nel nostro progetto.
Crea colors.dart
Crea un nuovo file di freccette in lib
denominato colors.dart
. Importa material.dart
e aggiungi const Color
valori:
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 a colori è stato creato da un designer con colori personalizzati (mostrati nell'immagine di seguito). Contiene colori che sono stati selezionati dal brand di Santuario e applicati all'editor dei temi materiali, che li ha ampliati per creare una tavolozza più completa. Questi colori non provengono dalle tavolozze dei colori Material 2014.
L'editor dei temi materiali li ha organizzati in tonalità etichettate numericamente, incluse le etichette 50, 100, 200, ... a 900 di ciascun colore. Santuario usa solo le tonalità 50, 100 e 300 del campione rosa e 900 del campione marrone.
Ogni parametro del colore di un widget è mappato a un colore di questi schemi. Ad esempio, il colore delle decorazioni di un campo di testo quando riceve attivamente input dovrebbe essere il colore principale del tema. Se quel colore non è accessibile (facile da vedere sullo sfondo), utilizzane un altro.
Ora che abbiamo i colori che vogliamo usare, possiamo applicarli alla UI. Per farlo, imposta i valori di un widget ThemeData che applichiamo all'istanza di MaterialApp nella parte superiore della gerarchia dei widget.
Personalizzare 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.ARROW al di fuori dell'ambito della classe SantuarioApp:
// 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 SantuarioApp (nel widget MaterialApp) come nuovo tema:
// TODO: Customize the theme (103)
theme: _kShrineTheme, // New code
Salvare il progetto. La schermata di accesso dovrebbe avere il seguente aspetto:
Android | iOS |
5. Modificare gli stili di tipografia e di etichetta
Oltre alle modifiche di colore, il designer ci ha anche fornito elementi tipografici specifici da utilizzare. ThemeData di Flutter include tre temi di testo. Ogni tema del testo è una raccolta di stili di testo, ad esempio "titolo" e "title". Utilizzeremo alcuni stili per l'app e cambieremo 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.
Risolvere i problemi relativi al file pubspec
Potresti visualizzare errori durante l'esecuzione di pub get se tagli e incolli la dichiarazione riportata sopra. Se visualizzi errori, inizia rimuovendo lo spazio vuoto iniziale e sostituendolo con spazi usando il rientro di due spazi. (due spazi prima
fonts:
, quattro spazi prima
family: Rubik
e così via).
Se viene visualizzato il messaggio I valori di mappatura non sono consentiti qui, controlla il rientro della linea che presenta il problema e il rientro delle righe superiori.
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,
);
}
Viene preso un TextTheme e viene modificato l'aspetto di titoli, titoli e sottotitoli.
Applicando l'fontFamily
in questo modo, le modifiche vengono applicate solo ai valori della scala tipografia specificati in copyWith()
(titolo, titolo, didascalia).
Per alcuni caratteri, stiamo impostando un peso del carattere personalizzato con incrementi di 100: w500 (peso pari a 500) corrisponde a mezzo e w400 corrisponde a regolare.
Utilizzare i nuovitemi di testo
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 a caldo), dato che abbiamo modificato i caratteri.
Android | iOS |
Il testo nelle schermate di accesso e in quello Home ha un aspetto diverso: parte del testo utilizza il carattere Rubik, mentre l'altro viene visualizzato in marrone anziché in bianco o nero. Anche le icone vengono visualizzate in marrone.
Ridurre il testo
Le etichette sono troppo grandi.
In home.dart
, modifica il valore 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
],
Centra e rilascia 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 modificale per centrarle:
// TODO: Align labels to the bottom and center (103)
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.center,
Salvare il progetto.
Android | iOS |
Sembra molto meglio.
Creare un tema per i campi di testo
Puoi anche scegliere un tema per la decorazione nei 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
. Rimuoviamo l'elemento. Se rimuovi filled
e specifichi il valore inputDecorationTheme
, ai campi di testo verrà applicato 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. Quando il campo Nome utente è attivo (durante la digitazione), la schermata di accesso dovrebbe avere il seguente aspetto:
Android | iOS |
Digita in un campo di testo: i bordi e le etichette mobili vengono visualizzati con il colore principale. Ma non è facile vederli. Non sono accessibili da chi ha difficoltà a distinguere i pixel che non hanno un contrasto di colore sufficientemente elevato. Per ulteriori informazioni, leggi l'articolo su colore e accessibilità delle linee guida sui materiali.
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 valore 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, supponiamo 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. Regola l'elevazione
Ora che hai assegnato alla pagina uno stile specifico e tipografico che corrisponda a Santuario, regola l'elevazione.
Modificare l'elevazione del pulsante SUCCESSIVO
L'elevazione predefinita per ElevatedButton
è 2. Saliamo più in alto.
In login.dart
, aggiungi un valore style:
al pulsante elevato 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 |
Regola l'elevazione della scheda
In questo momento, le schede sono visibili su una superficie bianca accanto al riquadro di navigazione del sito.
In home.dart
, aggiungi un valore elevation:
alle schede:
// 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 trendy, che definisce gli elementi a forma ottagonale o rettangolare. Implementiamo questo stile nelle schede della schermata Home e nei campi di testo e nei pulsanti nella schermata di accesso.
Modifica 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 decorativo del campo di testo per utilizzare il bordo degli angoli tagliati:
// 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, allora perché aggiungere una forma per il bordo? In questo modo, l'animazione a onde viene legata 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 usare anche elevatedButtonTheme
o textButtonTheme
in app.dart
. Questo rimane una sfida per lo studente.
Riavvio a caldo.
Android | iOS |
8. Modificare il layout
Ora modifichiamo il layout in modo da mostrare le schede con proporzioni e dimensioni diverse, in modo che ogni scheda risulti unica dalle altre.
Sostituire 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 in orizzontale con un motivo ispirato al tessuto.
9. (Facoltativo) Prova con un altro tema
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 provarlo, vediamo che aspetto ha Santuario 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()
come segue:
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. A questo punto dovrebbe essere visualizzato il nuovo tema.
Android | iOS |
Android | iOS |
Il risultato è molto diverso. Ripristina app.dart's
_buildShrineTheme
allo stato che era prima di questo passaggio. In alternativa, scarica il codice di avvio di 104.
10. Complimenti!
A questo punto hai creato un'app che presenta le specifiche di progettazione del tuo designer.
Passaggi successivi
Ora hai utilizzato le seguenti dimensioni di Material Flutter: tema, tipografia, elevazione e forma. Puoi esplorare altri componenti e sottosistemi nella libreria Material Flutter.
Analizza i file nella directory supplemental
per scoprire come abbiamo reso la griglia di layout asimmetrico a scorrimento orizzontale.
Cosa succede se il design pianificato dell'app contiene elementi che non hanno componenti nella raccolta? In MDC-104: Material Advanced Components, mostriamo come creare componenti personalizzati utilizzando la libreria Material Flutter per ottenere il look desiderato.