MDC-101 Android: nozioni di base di Material Components (MDC) (Kotlin)

logo_components_color_2x_web_96dp.png

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 per Android, Material Components for Android (MDC Android) unisce progettazione e ingegneria con una libreria di componenti per creare coerenza in tutta l'app. Man mano che il sistema Material Design si evolve, questi componenti vengono aggiornati per garantire un'implementazione coerente e perfetta a livello di pixel e il rispetto degli standard di sviluppo front-end di Google. MDC è disponibile anche per il 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?

Principiante Intermedio Avanzato

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

Scaricare l'app iniziale

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

… 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

  1. 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 kotlin -> shrine (o cerca shrine sul computer) per aprire il progetto Shipping.
  2. 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.
  3. 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.

  1. Vai al file build.gradle del modulo app e assicurati che il blocco dependencies includa una dipendenza da MDC 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'
}

Eseguire l'app iniziale

  1. Assicurati che la configurazione della build a sinistra del pulsante Esegui / Riproduci sia app.
  2. Premi il pulsante verde Esegui / Riproduci per creare ed eseguire l'app.
  3. Nella finestra Seleziona destinazione di distribuzione, se hai già un dispositivo Android elencato nei dispositivi disponibili, 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, e poi fai clic su Avanti.
  5. Nella schermata Immagine di sistema, seleziona una versione recente di Android, preferibilmente il livello API più alto. Se non è installato, fai clic sul link Scarica mostrato e completa il download.
  6. Fai clic su Avanti.
  7. Nella schermata Android Virtual Device (AVD), lascia le impostazioni invariate e fai clic su Fine.
  8. Seleziona un dispositivo Android dalla finestra di dialogo Destinazione di deployment.
  9. Fai clic su Ok.
  10. Android Studio crea l'app, la esegue il deployment e la apre automaticamente sul dispositivo di destinazione.

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.kt nella directory shrine -> app -> src -> main -> java -> com.google.codelabs.mdc.kotlin.shrine. Deve contenere:

MainActivity.kt

package com.google.codelabs.mdc.kotlin.shrine

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment

class MainActivity : AppCompatActivity(), NavigationHost {

   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setContentView(R.layout.shr_main_activity)

       if (savedInstanceState == null) {
           supportFragmentManager
                   .beginTransaction()
                   .add(R.id.container, LoginFragment())
                   .commit()
       }
   }

   override fun navigateTo(fragment: Fragment, addToBackstack: Boolean) {
       val transaction = supportFragmentManager
               .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.kt inizia una transazione Fragment per mostrare LoginFragment. Per questo codelab, modificheremo LoginFragment. 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à.

A questo punto, apri LoginFragment.kt.

LoginFragment.kt

package com.google.codelabs.mdc.kotlin.shrine

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment

class LoginFragment : Fragment() {

   override fun onCreateView(
           inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
       // Inflate the layout for this fragment
       val view = inflater.inflate(R.layout.shr_login_fragment, container, false)

       return view
   }
}

LoginFragment gonfia il file di layout shr_login_fragment e lo visualizza in onCreateView().

Ora 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" />
   </LinearLayout>
</ScrollView>

Qui possiamo vedere un <LinearLayout> con un <ImageView> in alto, che rappresenta il logo di Shrine.

Di seguito, sotto il logo è presente 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" />
</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:errorEnabled su true nell'elemento Password TextInputLayout. In questo modo, verrà aggiunto un riempimento aggiuntivo per il messaggio di errore sotto il campo di testo.
  • Imposta l'attributo android:inputType su "textPassword" nell'elemento Password TextInputEditText. 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" />
</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 Kotlin a LoginFragment.kt per collegare il pulsante "AVANTI" alla transizione a un altro fragmento.

Aggiungiamo un metodo booleano privato isPasswordValid in LoginFragment.kt 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.kt

private fun isPasswordValid(text: Editable?): Boolean {
   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.

Ora aggiungiamo un listener di tasti al campo TextInputEditText della password 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.kt

override fun onCreateView(
           inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
       // Inflate the layout for this fragment.
       val view = inflater.inflate(R.layout.shr_login_fragment, container, false)

       // Set an error if the password is less than 8 characters.
       view.next_button.setOnClickListener({
           if (!isPasswordValid(password_edit_text.text!!)) {
               password_text_input.error = getString(R.string.shr_error_password)
           } else {
               // Clear the error.
               password_text_input.error = null
           }
       })

       // Clear the error once more than 8 characters are typed.
       view.password_edit_text.setOnKeyListener({ _, _, _ ->
           if (isPasswordValid(password_edit_text.text!!)) {
               // Clear the error.
               password_text_input.error = null
           }
           false
       })

       return view
   }
}

Ora possiamo passare a un altro frammento. In onCreateView(), aggiorna OnClickListener per passare a un altro frammento quando la convalida degli errori va a buon fine. Il codice clickListener ora dovrebbe avere il seguente aspetto:

LoginFragment.kt

// Set an error if the password is less than 8 characters.
view.next_button.setOnClickListener({
   if (!isPasswordValid(password_edit_text.text!!)) {
       password_text_input.error = getString(R.string.shr_error_password)
   } else {
       // Clear the error.
       password_text_input.error = null
       // Navigate to the next Fragment.
       (activity as NavigationHost).navigateTo(ProductGridFragment(), false)
   }
})

Abbiamo aggiunto la riga (activity as NavigationHost).navigateTo(ProductGridFragment(), false) al else caso del listener di clic. Questa riga 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 Kotlin, la libreria Material Components for Android ti ha aiutato a creare una bellissima 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.

Sono riuscito a completare questo codelab con un ragionevole dispendio di tempo e impegno

Totalmente d'accordo D'accordo Indifferente In disaccordo Totalmente in disaccordo

Vorrei continuare a utilizzare i componenti Material in futuro

Totalmente d'accordo D'accordo Indifferente In disaccordo Totalmente in disaccordo