MDC-101 per Android: nozioni di base sui componenti materiali (MDC) (Java)

1. Introduzione

logo_components_color_2x_web_96dp.png

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

Cosa sono Material Design e Material Component per Android?

Material Design è un sistema per la creazione di prodotti digitali belli e audaci. 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 design e progettazione a una libreria di componenti per creare coerenza all'interno dell'applicazione. Man mano che il sistema Material Design si evolve, questi componenti vengono aggiornati per garantire un'implementazione perfetta in 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 dei quattro codelab che ti guideranno nella creazione di un'app chiamata Shrine, un'app per Android di e-commerce che vende abbigliamento e articoli per la casa. Scoprirai come personalizzare i componenti per adattarli a qualsiasi brand o stile utilizzando MDC-Android.

In questo codelab, creerai una pagina di accesso per il Santuario contenente:

  • Due campi di testo, uno per inserire il nome utente e l'altro per la password
  • Due pulsanti, uno per "Annulla" e uno per "Avanti"
  • Il nome dell'app (Shrine)
  • Immagine del logo di Santuario

4cb0c218948144b4.png

Componenti di MDC per Android in questo codelab

  • Campo di testo
  • Pulsante

Che cosa ti serve

  • Conoscenza di base dello sviluppo di Android
  • Android Studio (scaricalo qui se non l'hai ancora fatto)
  • Un emulatore o un dispositivo Android (disponibile tramite Android Studio)
  • Il codice di esempio (vedi il passaggio successivo)

Come giudichi il tuo livello di esperienza nello sviluppo di app per Android?

Principiante Livello intermedio Eccellente

2. Configurazione dell'ambiente di sviluppo

Avvia Android Studio

Quando apri Android Studio, dovrebbe essere visualizzata una finestra chiamata "Ti diamo il benvenuto in Android Studio". Tuttavia, se è la prima volta che avvii Android Studio, segui la procedura della Configurazione guidata di Android Studio con i valori predefiniti. Questo passaggio può richiedere diversi minuti per scaricare e installare i file necessari, quindi non esitare a lasciarlo in esecuzione in background mentre esegui la prossima sezione.

Scarica l'app codelab iniziale

L'app iniziale si trova nella directory material-components-android-codelabs-101-starter/java.

...o clonarlo da GitHub

Per clonare questo codelab da GitHub, esegui questi 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

  1. Al termine della configurazione guidata e visualizzata la finestra Ti diamo il benvenuto in Android Studio, fai clic su Apri un progetto Android Studio esistente. Passa alla directory in cui hai installato il codice di esempio e seleziona java -> santuario (o cerca shrine sul computer) per aprire il progetto Santuario.
  2. Attendi un momento affinché Android Studio crei e sincronizzi il progetto, come mostrato dagli indicatori di attività nella parte inferiore della finestra di Android Studio.
  3. A questo punto, Android Studio potrebbe generare alcuni errori di generazione perché non disponi dell'SDK Android o degli strumenti di sviluppo, come quello mostrato di seguito. Segui le istruzioni in Android Studio per installarle/aggiornarle e sincronizzare il progetto.

F5H6srsw_5xOPGFpKrm1RwgewatxA_HUbDI1PWoQUAoJcT6DpfBOkAYwq3S-2vUHvweUaFgAmG7BtUKkGouUbhTwXQh53qec8tO5eVecdlo7QIoLc8rNxFEBb8l7RlS-KzBbZOzVhA

Aggiungi le dipendenze del progetto

Il progetto richiede una dipendenza dalla libreria di supporto Android MDC. Il codice campione che hai scaricato dovrebbe già avere questa dipendenza elencata, ma è buona norma svolgere i seguenti passaggi per averne la certezza.

  1. Passa al file build.gradle del modulo app e assicurati che il blocco dependencies includa una dipendenza su MDC per Android:
api 'com.google.android.material:material:1.1.0-alpha06'
  1. (Facoltativo) Se necessario, modifica il file build.gradle per 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'
}

Esegui l'app iniziale

  1. Assicurati che la configurazione della build a sinistra del pulsante Esegui / Riproduci sia app.
  2. Premi il pulsante Esegui / Riproduci verde per creare ed eseguire l'app.
  3. Se tra i dispositivi disponibili è già elencato un dispositivo Android, nella finestra Seleziona la destinazione del deployment vai al passaggio 8. In caso contrario, fai clic su Crea nuovo dispositivo virtuale.
  4. Nella schermata Seleziona hardware, seleziona uno smartphone, ad esempio Pixel 2, quindi fai clic su Avanti.
  5. Nella schermata Immagine di sistema, seleziona una versione di Android recente, preferibilmente il livello API più elevato. Se non è installata, fai clic sul link Scarica visualizzato e completa il download.
  6. Fai clic su Avanti.
  7. Nella schermata Dispositivo virtuale Android (AVD), lascia le impostazioni invariate e fai clic su Fine.
  8. Seleziona un dispositivo Android dalla finestra di dialogo della destinazione dell'implementazione.
  9. Fai clic su Ok.
  10. Android Studio crea l'app, la distribuisce e la apre automaticamente sul dispositivo di destinazione.

Operazione riuscita. Il codice di avvio per la pagina di accesso di Santuario dovrebbe essere in esecuzione nell'emulatore. Dovresti vedere il nome "Shrine" e il logo del santuario immediatamente sotto.

e7ed014e84755811.png

Diamo un'occhiata al codice. Nel nostro codice di esempio, abbiamo fornito un semplice framework di navigazione Fragment per visualizzare i frammenti e navigare tra i frammenti.

Apri MainActivity.java nella directory shrine -> app -> src -> main -> java -> com.google.codelabs.mdc.java.shrine. Dovrebbe contenere quanto segue:

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();
   }
}

In questa attività viene visualizzato il file di layout R.layout.shr_main_activity, definito in shr_main_activity.xml.

Puoi vedere che in onCreate(), MainActivity.java avvia una transazione Fragment per mostrare LoginFragment. LoginFragment. Questi sono gli elementi che modificheremo in questo codelab. L'attività implementa anche un metodo navigateTo(Fragment), definito in NavigationHost, che consente a qualsiasi frammento di passare a un frammento diverso.

Comando + clic (o Ctrl + clic) shr_main_activity nel file dell'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 frammenti 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 come si presenta la 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 lo "Santuario" .

A seguire, c'è un tag <TextView> che rappresenta lo "SHRINE" dell'etichetta. Il testo di questa etichetta è una risorsa stringa denominata @string/shr_app_name. Se premi Comando + clic (o Ctrl + 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 di tipo stringa. Quando verranno aggiunte altre risorse di tipo stringa in futuro, queste verranno definite qui. Ogni risorsa in questo file deve avere un prefisso shr_ per indicare che fanno parte dell'app Santuario.

Ora che hai acquisito familiarità con il codice di base, implementiamo il nostro primo componente.

3. Aggiungi campi di testo

Per iniziare, aggiungeremo due campi di testo alla nostra pagina di accesso per consentire agli utenti di inserire nome utente e password. Utilizzeremo il componente Campo di testo MDC, che include una funzionalità integrata che visualizza un'etichetta mobile e messaggi di errore.

d83c47fb4aed3a82.png

Aggiungere il file XML

In shr_login_fragment.xml, aggiungi due elementi TextInputLayout con un elemento secondario TextInputEditText all'interno di <LinearLayout>, sotto "SHRINE" etichetta <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 riportato sopra rappresenta due campi di testo, ciascuno composto 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 vedere queste risorse di stringa.

strings.xml

...
<string name="shr_hint_username">Username</string>
<string name="shr_hint_password">Password</string>
...

Aggiungi convalida input

I componenti di TextInputLayout forniscono una funzionalità integrata di feedback sugli errori.

Per mostrare il feedback sull'errore, apporta le seguenti modifiche a shr_login_fragment.xml:

  • Imposta l'attributo app:errorEnabled su true nell'elemento Password TextInputLayout. Verrà aggiunta un'ulteriore spaziatura interna per il messaggio di errore sotto il campo di testo.
  • Imposta l'attributo android:inputType su "textPassword" sull'elemento Password TextInputEditText. Il testo inserito nel campo della password verrà nascosto.

Con queste modifiche, i campi di testo di 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 vedere una pagina con due campi di testo per "Nome utente" e "Password".

Guarda l'animazione dell'etichetta mobile:

333184b615aed4f7.gif

4. Aggiungere pulsanti

Successivamente, aggiungeremo due pulsanti alla pagina di accesso: "Annulla" e "Avanti". Utilizzeremo il componente Pulsante MDC, che è integrato nell'iconico effetto inchiostro a inchiostro.

4cb0c218948144b4.png

Aggiungere il file XML

In shr_login_fragment.xml, aggiungi <RelativeLayout> a <LinearLayout>, sotto gli elementi TextInputLayout. Poi aggiungi due elementi <MaterialButton> a <RelativeLayout>.

Il file XML risultante dovrebbe avere l'aspetto seguente:

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'onda di inchiostro quando tocchi ciascun pulsante.

9dd162d65e4a92a2.gif

5. Vai al frammento successivo

Infine, aggiungeremo del codice Java a LoginFragment.java per collegare il nostro "NEXT" pulsante a un altro frammento. Puoi notare che a ogni componente che abbiamo aggiunto al nostro layout è stato assegnato un id. Utilizzeremo questi id per fare riferimento ai componenti del nostro codice e aggiungere alcuni errori di controllo e navigazione.

Aggiungiamo un metodo isPasswordValid booleano privato in LoginFragment.java sotto onCreateView(), con una logica per determinare se la password è valida o meno. Ai fini di questa demo, ci assicureremo che la password sia composta da 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;
}

A questo punto, 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 di clic deve essere posizionato tra la riga di rigonfiamento e la riga return view.

A questo punto, aggiungiamo un listener di chiavi alla password TextInputEditText per rimanere in ascolto degli eventi chiave che cancellano l'errore. Questo listener deve utilizzare anche isPasswordValid() per verificare se la password è valida. Puoi aggiungerlo direttamente sotto il listener di clic in onCreateView().

Il tuo metodo onCreateView() dovrebbe avere ora un aspetto simile al seguente:

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 dell'errore 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 dei clic 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. Attualmente questa è una pagina vuota, su cui lavorerai in MDC-102.

Ora, crea l'app. Procedi e premi il pulsante Avanti.

Ce l'hai fatta! Questa schermata sarà il punto di partenza del nostro prossimo codelab su cui lavorerai in MDC-102.

6. Fine

Utilizzando il markup XML di base e circa 30 righe di Java, la libreria Material Components per Android ti ha aiutato a creare una fantastica pagina di accesso conforme alle linee guida di Material Design e che abbia l'aspetto e il comportamento coerente su tutti i dispositivi.

Passaggi successivi

Il campo di testo e il pulsante sono due componenti fondamentali della libreria MDC per Android, ma ce ne sono molti altri. Puoi esplorare gli altri componenti di MDC Android. In alternativa, consulta l'articolo MDC 102: Struttura e layout di Material Design per scoprire di più sulla barra delle app in alto, sulla visualizzazione schede e sul layout a griglia. Grazie per aver provato Material Components. Speriamo che questo codelab ti sia piaciuto.

Ho completato questo codelab con una quantità di tempo e di sforzi ragionevoli

Totalmente d'accordo D'accordo Né chiara, né confusa In disaccordo Totalmente in disaccordo

Vorrei continuare a utilizzare Material Components in futuro

Totalmente d'accordo D'accordo Né chiara, né confusa In disaccordo Totalmente in disaccordo