Material Components (MDC) aiuta 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 |
Che cosa sono Material Design e Material Components per Android?
Material Design è un sistema per creare prodotti digitali audaci e accattivanti. Unendo stile, branding, interazione e movimento in un insieme coerente di principi e componenti, i team di prodotto possono realizzare il loro massimo potenziale di progettazione.
Per le applicazioni Android, Material Components for Android (MDC Android) unisce progettazione e ingegneria con una libreria di componenti per creare coerenza nell'applicazione. Man mano che il sistema Material Design si evolve, questi componenti vengono aggiornati per garantire un'implementazione coerente e perfetta al pixel e il rispetto degli standard di sviluppo front-end di Google. MDC è disponibile anche per web, iOS e Flutter.
In questo codelab, creerai una pagina di accesso utilizzando diversi componenti di MDC Android.
Cosa creerai
Questo codelab è il primo di quattro che ti guideranno nella creazione di un'app chiamata Shrine, un'app e-commerce per Android che vende abbigliamento e articoli per la casa. Mostrerà come personalizzare i componenti per riflettere qualsiasi brand o stile utilizzando MDC-Android.
In questo codelab creerai una pagina di accesso per Shrine che contiene:
- Due campi di testo, uno per inserire un nome utente e l'altro per una password
- Due pulsanti: uno per "Annulla" e uno per "Avanti".
- Il nome dell'app (Shrine)
- Un'immagine del logo di Shrine

Componenti MDC Android in questo codelab
- Campo di testo
- Pulsante
Che cosa ti serve
- Conoscenza di base dello sviluppo Android
- Android Studio (scaricalo qui se non lo hai già)
- Un emulatore o un dispositivo Android (disponibile tramite Android Studio)
- Il codice di esempio (vedi il passaggio successivo)
Come valuteresti il tuo livello di esperienza nella creazione di app per Android?
Avvia Android Studio
Quando apri Android Studio, dovrebbe essere visualizzata una finestra con il titolo "Welcome to Android Studio" (Benvenuto in Android Studio). Tuttavia, se è la prima volta che avvii Android Studio, segui i passaggi della procedura guidata di configurazione di Android Studio con i valori predefiniti. Il download e l'installazione dei file necessari per questo passaggio possono richiedere diversi minuti, quindi puoi lasciarlo in esecuzione in background mentre svolgi la sezione successiva.
Scarica l'app codelab iniziale
L'app iniziale si trova nella directory material-components-android-codelabs-101-starter/java.
… oppure clonalo da GitHub
Per clonare questo codelab da GitHub, esegui i seguenti comandi:
git clone https://github.com/material-components/material-components-android-codelabs cd material-components-android-codelabs/ git checkout 101-starter
Carica il codice di avvio in Android Studio
- Al termine della configurazione guidata e alla visualizzazione della finestra Benvenuto in Android Studio, fai clic su Apri un progetto Android Studio esistente. Vai alla directory in cui hai installato il codice di esempio e seleziona java -> shrine (o cerca shrine sul computer) per aprire il progetto Shrine.
- Attendi un attimo che Android Studio crei e sincronizzi il progetto, come indicato dagli indicatori di attività nella parte inferiore della finestra di Android Studio.
- A questo punto, Android Studio potrebbe generare alcuni errori di build perché mancano l'SDK Android o gli strumenti di build, come quello mostrato di seguito. Segui le istruzioni in Android Studio per installare/aggiornare questi elementi e sincronizzare il progetto.
Aggiungere le dipendenze del progetto
Il progetto richiede una dipendenza dalla libreria di supporto MDC Android. Il codice campione che hai scaricato dovrebbe già avere questa dipendenza elencata, ma è buona norma eseguire i seguenti passaggi per assicurarsi.
- Vai al file
build.gradledel moduloappe assicurati che il bloccodependenciesincluda una dipendenza da MDC Android:
api 'com.google.android.material:material:1.1.0-alpha06'
- (Facoltativo) Se necessario, modifica il file
build.gradleper aggiungere le seguenti dipendenze e sincronizza il progetto.
dependencies {
api 'com.google.android.material:material:1.1.0-alpha06'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'com.android.volley:volley:1.1.1'
implementation 'com.google.code.gson:gson:2.8.5'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.21"
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:core:1.1.0'
androidTestImplementation 'androidx.test.ext:junit:1.1.0'
androidTestImplementation 'androidx.test:runner:1.2.0-alpha05'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0-alpha05'
}Eseguire l'app iniziale
|
Operazione riuscita. Il codice iniziale per la pagina di accesso di Shrine dovrebbe essere in esecuzione nell'emulatore. Dovresti vedere il nome "Shrine" e il logo di Shrine appena sotto.

Diamo un'occhiata al codice. Nel nostro codice di esempio abbiamo fornito un semplice framework di navigazione Fragment per visualizzare i fragment e spostarsi tra di essi.
Apri MainActivity.java nella directory shrine -> app -> src -> main -> java -> com.google.codelabs.mdc.java.shrine. Deve contenere:
MainActivity.java
package com.google.codelabs.mdc.java.shrine;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
public class MainActivity extends AppCompatActivity implements NavigationHost {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.shr_main_activity);
if (savedInstanceState == null) {
getSupportFragmentManager()
.beginTransaction()
.add(R.id.container, new LoginFragment())
.commit();
}
}
/**
* Navigate to the given fragment.
*
* @param fragment Fragment to navigate to.
* @param addToBackstack Whether or not the current fragment should be added to the backstack.
*/
@Override
public void navigateTo(Fragment fragment, boolean addToBackstack) {
FragmentTransaction transaction =
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.container, fragment);
if (addToBackstack) {
transaction.addToBackStack(null);
}
transaction.commit();
}
}Questa attività mostra il file di layout R.layout.shr_main_activity, definito in shr_main_activity.xml.
Puoi vedere che in onCreate(), MainActivity.java inizia una transazione Fragment per mostrare LoginFragment. LoginFragment. Questo è ciò che modificheremo per questo codelab. L'attività implementa anche un metodo navigateTo(Fragment), definito in NavigationHost, che consente a qualsiasi frammento di passare a un altro frammento.
Command + Click (o Control + Click) shr_main_activity nel file di attività per aprire il file di layout oppure vai al file di layout in app -> res -> layout -> shr_main_activity.xml.
shr_main_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" />Qui vediamo un semplice <FrameLayout> che funge da contenitore per tutti i fragment visualizzati dall'attività. Apriamo LoginFragment.java.
LoginFragment.java
package com.google.codelabs.mdc.java.shrine;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
/**
* Fragment representing the login screen for Shrine.
*/
public class LoginFragment extends Fragment {
@Override
public View onCreateView(
@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.shr_login_fragment, container, false);
// Snippet from "Navigate to the next Fragment" section goes here.
return view;
}
// "isPasswordValid" from "Navigate to the next Fragment" section method goes here
}LoginFragment gonfia il file di layout shr_login_fragment e lo visualizza in onCreateView(). Diamo un'occhiata al file di layout shr_login_fragment.xml per vedere l'aspetto della pagina di accesso.
shr_login_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/loginPageBackgroundColor"
tools:context=".LoginFragment">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipChildren="false"
android:clipToPadding="false"
android:orientation="vertical"
android:padding="24dp"
android:paddingTop="16dp">
<ImageView
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="48dp"
android:layout_marginBottom="16dp"
app:srcCompat="@drawable/shr_logo" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="132dp"
android:text="@string/shr_app_name"
android:textAllCaps="true"
android:textSize="16sp" />
<!-- Snippet from "Add text fields" section goes here. -->
<!-- Snippet from "Add buttons" section goes here. -->
</LinearLayout>
</ScrollView>Qui possiamo vedere un <LinearLayout> con un <ImageView> in alto, che rappresenta il logo "Santuario".
Segue un tag <TextView> che rappresenta l'etichetta "SHRINE". Il testo di questa etichetta è una risorsa stringa denominata @string/shr_app_name. Se fai Command + clic (o Control + clic) sul nome della risorsa stringa o apri app -> res -> values -> strings.xml, puoi visualizzare il file strings.xml in cui sono definite le risorse stringa. Quando in futuro verranno aggiunte altre risorse stringa, verranno definite qui. Ogni risorsa in questo file deve avere un prefisso shr_ per indicare che fa parte dell'app Shrine.
Ora che hai familiarità con il codice iniziale, implementiamo il nostro primo componente.
Per iniziare, aggiungeremo due campi di testo alla nostra pagina di accesso in cui gli utenti potranno inserire il nome utente e la password. Utilizzeremo il componente Campo di testo MDC, che include funzionalità integrate che mostrano un'etichetta mobile e messaggi di errore.

Aggiungere l'XML
In shr_login_fragment.xml, aggiungi due elementi TextInputLayout con un elemento secondario TextInputEditText all'interno di <LinearLayout>, sotto l'etichetta "SHRINE" <TextView>:
shr_login_fragment.xml
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:hint="@string/shr_hint_username">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text"
android:maxLines="1" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/password_text_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:hint="@string/shr_hint_password">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/password_edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</com.google.android.material.textfield.TextInputLayout>Lo snippet precedente rappresenta due campi di testo, ognuno dei quali è costituito da un elemento <TextInputLayout> e da un elemento secondario <TextInputEditText>. Il testo del suggerimento per ogni campo di testo è specificato nell'attributo android:hint.
Abbiamo incluso due nuove risorse stringa per il campo di testo: @string/shr_hint_username e @string/shr_hint_password. Apri strings.xml per visualizzare queste risorse di stringhe.
strings.xml
...
<string name="shr_hint_username">Username</string>
<string name="shr_hint_password">Password</string>
...Aggiungere la convalida dell'input
I componenti TextInputLayout forniscono funzionalità di feedback sugli errori integrate.
Per mostrare il feedback sugli errori, apporta le seguenti modifiche a shr_login_fragment.xml:
- Imposta l'attributo
app:errorEnabledsu true nell'elemento PasswordTextInputLayout. In questo modo, verrà aggiunto un riempimento aggiuntivo per il messaggio di errore sotto il campo di testo. - Imposta l'attributo
android:inputTypesu "textPassword" nell'elemento PasswordTextInputEditText. In questo modo, il testo inserito nel campo della password verrà nascosto.
Con queste modifiche, i campi di testo in shr_login_fragment.xml dovrebbero avere il seguente aspetto:
shr_login_fragment.xml
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:hint="@string/shr_hint_username">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text"
android:maxLines="1" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/password_text_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:hint="@string/shr_hint_password"
app:errorEnabled="true">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/password_edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPassword"/>
</com.google.android.material.textfield.TextInputLayout>Ora prova a eseguire l'app. Dovresti visualizzare una pagina con due campi di testo per "Nome utente" e "Password".
Guarda l'animazione dell'etichetta mobile:

A questo punto, aggiungiamo due pulsanti alla nostra pagina di accesso: "Annulla" e "Avanti". Utilizzeremo il componente Pulsante MDC, che include l'iconico effetto increspatura dell'inchiostro di Material Design.

Aggiungere l'XML
In shr_login_fragment.xml, aggiungi un <RelativeLayout> a <LinearLayout>, sotto gli elementi TextInputLayout. Quindi, aggiungi due elementi <MaterialButton> a <RelativeLayout>.
Il file XML risultante dovrebbe avere il seguente aspetto:
shr_login_fragment.xml
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.button.MaterialButton
android:id="@+id/next_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:text="@string/shr_button_next" />
<com.google.android.material.button.MaterialButton
android:id="@+id/cancel_button"
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="12dp"
android:layout_marginRight="12dp"
android:layout_toStartOf="@id/next_button"
android:layout_toLeftOf="@id/next_button"
android:text="@string/shr_button_cancel" />
</RelativeLayout>È tutto. Quando esegui l'app, viene visualizzata un'increspatura di inchiostro quando tocchi ogni pulsante.

Infine, aggiungeremo del codice Java a LoginFragment.java per collegare il pulsante "AVANTI" a un altro frammento. Noterai che a ciascuno dei componenti che abbiamo aggiunto al nostro layout è stato assegnato un id. Utilizzeremo questi id per fare riferimento ai componenti nel nostro codice e aggiungere alcuni controlli degli errori e la navigazione.
Aggiungiamo un metodo booleano privato isPasswordValid in LoginFragment.java sotto onCreateView(), con la logica per determinare se la password è valida o meno. Ai fini di questa demo, ci assicureremo solo che la password contenga almeno 8 caratteri:
LoginFragment.java
/*
In reality, this will have more complex logic including, but not limited to, actual
authentication of the username and password.
*/
private boolean isPasswordValid(@Nullable Editable text) {
return text != null && text.length() >= 8;
}Successivamente, aggiungi un listener di clic al pulsante "Avanti" che imposta e cancella l'errore in base al metodo isPasswordValid() appena creato. In onCreateView(), questo listener dei clic deve essere posizionato tra la riga dell'inflater e la riga return view.
Successivamente, aggiungiamo un listener di tasti alla password TextInputEditText per rilevare gli eventi chiave che cancellerebbero l'errore. Questo listener deve utilizzare anche isPasswordValid() per verificare se la password è valida o meno. Puoi aggiungerlo direttamente sotto il listener di clic in onCreateView().
Il metodo onCreateView() dovrebbe ora avere un aspetto simile a questo:
LoginFragment.java
@Override
public View onCreateView(
@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.shr_login_fragment, container, false);
final TextInputLayout passwordTextInput = view.findViewById(R.id.password_text_input);
final TextInputEditText passwordEditText = view.findViewById(R.id.password_edit_text);
MaterialButton nextButton = view.findViewById(R.id.next_button);
// Set an error if the password is less than 8 characters.
nextButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (!isPasswordValid(passwordEditText.getText())) {
passwordTextInput.setError(getString(R.string.shr_error_password));
} else {
passwordTextInput.setError(null); // Clear the error
}
}
});
// Clear the error once more than 8 characters are typed.
passwordEditText.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View view, int i, KeyEvent keyEvent) {
if (isPasswordValid(passwordEditText.getText())) {
passwordTextInput.setError(null); //Clear the error
}
return false;
}
});
return view;
} Ora possiamo passare a un altro frammento. Aggiorna OnClickListener in onCreateView() per passare a un altro frammento quando la convalida degli errori ha esito positivo. Puoi farlo aggiungendo la seguente riga per passare a ProductGridFragment al caso else del listener di clic:
LoginFragment.java
...
((NavigationHost) getActivity()).navigateTo(new ProductGridFragment(), false); // Navigate to the next Fragment
...Il listener di clic ora dovrebbe avere il seguente aspetto:
LoginFragment.java
...
MaterialButton nextButton = view.findViewById(R.id.next_button);
// Set an error if the password is less than 8 characters.
nextButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (!isPasswordValid(passwordEditText.getText())) {
passwordTextInput.setError(getString(R.string.shr_error_password));
} else {
passwordTextInput.setError(null); // Clear the error
((NavigationHost) getActivity()).navigateTo(new ProductGridFragment(), false); // Navigate to the next Fragment
}
}
});
...Questa nuova riga di codice chiama il metodo navigateTo() da MainActivity per passare a un nuovo frammento: ProductGridFragment. Al momento questa è una pagina vuota su cui lavorerai in MDC-102.
Ora crea l'app. Premi il pulsante Avanti.
Ce l'hai fatta! Questa schermata sarà il punto di partenza del nostro prossimo codelab, che affronterai in MDC-102.
Utilizzando il markup XML di base e circa 30 righe di Java, la libreria Material Components for Android ti ha aiutato a creare una splendida pagina di accesso conforme alle linee guida di Material Design e che ha un aspetto e un comportamento coerenti su tutti i dispositivi.
Passaggi successivi
Il campo di testo e il pulsante sono due componenti principali della libreria MDC per Android, ma ce ne sono molti altri. Puoi esplorare il resto dei componenti in MDC Android. In alternativa, consulta MDC 102: Material Design Structure and Layout per scoprire di più sulla barra delle app superiore, sulla visualizzazione schede e sul layout a griglia. Grazie per aver provato Material Components. Ci auguriamo che questo codelab ti sia piaciuto.