MDC-101 Android: Material Components (MDC) Basics (Kotlin)

1. Einführung

logo_components_color_2x_web_96dp.png

Mit Material-Komponenten (MDC) können Entwickler Material Design implementieren. MDC wurde von einem Team aus Ingenieuren und UX-Designern bei Google entwickelt und bietet Dutzende von ansprechenden und funktionalen UI-Komponenten. Es ist für Android, iOS, das Web und Flutter verfügbar.material.io/develop

Was sind Material Design und Material-Komponenten für Android?

Material Design ist ein System zum Erstellen ansprechender digitaler Produkte. Durch die Kombination von Stil, Branding, Interaktion und Motion unter einem einheitlichen Satz von Prinzipien und Komponenten können Produktteams ihr größtes Designpotenzial ausschöpfen.

Für Android-Anwendungen vereint Material-Komponenten für Android (MDC Android) Design und Technik mit einer Bibliothek von Komponenten, die für Konsistenz in Ihrer App sorgen. Da sich das Material Design-System weiterentwickelt, werden diese Komponenten aktualisiert, um eine konsistente, pixelgenaue Implementierung und die Einhaltung der Google-Standards für die Frontend-Entwicklung zu gewährleisten. MDC ist auch für das Web, iOS und Flutter verfügbar.

In diesem Codelab erstellen Sie eine Anmeldeseite mit mehreren Komponenten von MDC Android.

Aufgaben

Dieses Codelab ist das erste von vier Codelabs, in denen Sie eine App namens Shrine erstellen. Dabei handelt es sich um eine E‑Commerce-Android-App, in der Kleidung und Haushaltswaren verkauft werden. Sie erfahren, wie Sie Komponenten mit MDC Android anpassen können, um sie an eine Marke oder einen Stil anzupassen.

In diesem Codelab erstellen Sie eine Anmeldeseite für Shrine, die Folgendes enthält:

  • Zwei Textfelder, eines für die Eingabe eines Nutzernamens und das andere für ein Passwort
  • Zwei Schaltflächen, eine für „Abbrechen“ und eine für „Weiter“
  • Der Name der App (Shrine)
  • Ein Bild des Shrine-Logos

4cb0c218948144b4.png

MDC Android-Komponenten in diesem Codelab

  • Textfeld
  • Schaltfläche

Voraussetzungen

  • Grundkenntnisse der Android-Entwicklung
  • Android Studio (falls noch nicht vorhanden, hier herunterladen)
  • Ein Android-Emulator oder ‑Gerät (über Android Studio verfügbar)
  • Der Beispielcode (siehe nächster Schritt)

Wie würden Sie Ihre Erfahrung bei der Entwicklung von Android-Apps bewerten?

Anfänger Fortgeschritten Experte

2. Entwicklungsumgebung einrichten

Android Studio starten

Wenn Sie Android Studio öffnen, sollte ein Fenster mit dem Titel "Welcome to Android Studio" (Willkommen in Android Studio) angezeigt werden. Wenn Sie Android Studio jedoch zum ersten Mal starten, führen Sie die Schritte des Android Studio Setup Wizard (Android Studio-Einrichtungsassistent) mit den Standardwerten aus. Dieser Schritt kann einige Minuten dauern, da die erforderlichen Dateien heruntergeladen und installiert werden müssen. Sie können ihn also im Hintergrund ausführen, während Sie mit dem nächsten Abschnitt fortfahren.

Starter-App für das Codelab herunterladen

Die Starter-App befindet sich im Verzeichnis material-components-android-codelabs-101-starter/kotlin.

...oder aus GitHub klonen

Führen Sie die folgenden Befehle aus, um dieses Codelab aus GitHub zu klonen:

git clone https://github.com/material-components/material-components-android-codelabs
cd material-components-android-codelabs/
git checkout 101-starter

Starter-Code in Android Studio laden

  1. Wenn der Einrichtungsassistent abgeschlossen ist und das Fenster Welcome to Android Studio (Willkommen in Android Studio) angezeigt wird, klicken Sie auf Open an existing Android Studio project (Vorhandenes Android Studio-Projekt öffnen). Rufen Sie das Verzeichnis auf, in dem Sie den Beispielcode installiert haben, und wählen Sie kotlin -> shrine aus (oder suchen Sie auf Ihrem Computer nach shrine), um das Projekt „Shipping“ zu öffnen.
  2. Warten Sie einen Moment, bis Android Studio das Projekt erstellt und synchronisiert hat. Dies wird durch Aktivitätsindikatoren unten im Android Studio-Fenster angezeigt.
  3. An dieser Stelle können in Android Studio einige Build-Fehler auftreten, weil das Android SDK oder Build-Tools fehlen, z. B. der unten gezeigte Fehler. Folgen Sie der Anleitung in Android Studio, um diese zu installieren oder zu aktualisieren, und synchronisieren Sie Ihr Projekt.

KzoYWC1S7Se7yL8igi1vXF_mbVxAdl2lg5kb7RODrsVpEng0G6U3NK1Qnn0faBBZd2u71yMXioy9tD-7fv3NXvVO4N3EtMMeWDTmqBMMl6egd9R5uXX0T_SKmahbmRor3wZZHX0ByA

Projektabhängigkeiten hinzufügen

Für das Projekt ist eine Abhängigkeit von der MDC Android-Supportbibliothek erforderlich. Im heruntergeladenen Beispielcode sollte diese Abhängigkeit bereits aufgeführt sein. Es empfiehlt sich jedoch, die folgenden Schritte auszuführen, um sicherzugehen.

  1. Rufen Sie die Datei build.gradle des Moduls app auf und prüfen Sie, ob der Block dependencies eine Abhängigkeit von MDC Android enthält:
api 'com.google.android.material:material:1.1.0-alpha06'
  1. (Optional) Bearbeiten Sie bei Bedarf die Datei build.gradle, um die folgenden Abhängigkeiten hinzuzufügen und das Projekt zu synchronisieren.
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'
}

Starter-App ausführen

  1. Prüfen Sie, ob die Build-Konfiguration links neben der Schaltfläche Run / Play (Ausführen/Wiedergabe) auf app festgelegt ist.
  2. Klicken Sie auf die grüne Schaltfläche Run / Play (Ausführen/Wiedergabe), um die App zu erstellen und auszuführen.
  3. Wenn im Fenster Select Deployment Target (Bereitstellungsziel auswählen) bereits ein Android-Gerät unter den verfügbaren Geräten aufgeführt ist, fahren Sie mit Schritt 8 fort. Klicken Sie andernfalls auf Create New Virtual Device (Neues virtuelles Gerät erstellen).
  4. Wählen Sie auf dem Bildschirm Select Hardware (Hardware auswählen) ein Smartphone aus, z. B. Pixel 2 , und klicken Sie dann auf Next (Weiter).
  5. Wählen Sie auf dem Bildschirm System Image (Systemabbild) eine aktuelle Android-Version aus, vorzugsweise die höchste API-Ebene. Wenn sie nicht installiert ist, klicken Sie auf den Link Download (Herunterladen) und schließen Sie den Download ab.
  6. Klicken Sie auf Next (Weiter).
  7. Lassen Sie die Einstellungen auf dem Android Virtual Device (AVD) Bildschirm unverändert und klicken Sie auf Finish.
  8. Wählen Sie im Dialogfeld für das Bereitstellungsziel ein Android-Gerät aus.
  9. Klicken Sie auf OK.
  10. Android Studio erstellt die App, stellt sie bereit und öffnet sie automatisch auf dem Zielgerät.

Fertig! Der Starter-Code für die Anmeldeseite von Shrine sollte in Ihrem Emulator ausgeführt werden. Sie sollten den Namen „Shrine“ und das Shrine-Logo direkt darunter sehen.

e7ed014e84755811.png

Sehen wir uns den Code an. Wir haben in unserem Beispielcode ein einfaches Fragment-Navigationsframework bereitgestellt, mit dem Fragmente angezeigt und zwischen Fragmenten navigiert werden kann.

Öffnen Sie MainActivity.kt im Verzeichnis shrine -> app -> src -> main -> java -> com.google.codelabs.mdc.kotlin.shrine. Es sollte Folgendes enthalten:

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

Diese Aktivität zeigt die Layoutdatei R.layout.shr_main_activity an, die in shr_main_activity.xml definiert ist.

In onCreate(), MainActivity.kt startet eine Fragment-Transaktion, um LoginFragment anzuzeigen. In diesem Codelab ändern wir LoginFragment. Die Aktivität implementiert auch eine Methode navigateTo(Fragment), die in NavigationHost definiert ist und mit der jedes Fragment zu einem anderen Fragment navigieren kann.

Command + Klick (oder Strg + Klick) shr_main_activity in der Aktivitätsdatei, um die Layoutdatei zu öffnen, oder rufen Sie die Layoutdatei unter app -> res -> layout -> shr_main_activity.xml auf.

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"/>

Hier sehen wir ein einfaches <FrameLayout>, das als Container für alle Fragmente dient, die von der Aktivität angezeigt werden.

Öffnen wir nun 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 erweitert die Layoutdatei shr_login_fragment und zeigt sie in onCreateView() an.

Sehen wir uns nun die Layoutdatei shr_login_fragment.xml an, um zu sehen, wie die Anmeldeseite aussieht.

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>

Hier sehen wir ein <LinearLayout> mit einem <ImageView> oben, das das Shrine-Logo darstellt.

Danach folgt ein <TextView>-Tag, das das Shrine-Label unter dem Logo darstellt. Der Text für dieses Label ist eine String-Ressource mit dem Namen @string/shr_app_name. Wenn Sie Command + Klick (oder Strg + Klick) auf den Namen der String-Ressource ausführen oder app -> res -> values -> strings.xml öffnen, sehen Sie die Datei strings.xml, in der String-Ressourcen definiert sind. Wenn in Zukunft weitere String-Ressourcen hinzugefügt werden, werden sie hier definiert. Jede Ressource in dieser Datei sollte das Präfix shr_ haben, um anzugeben, dass sie Teil der Shrine-App ist.

Nachdem Sie sich mit dem Starter-Code vertraut gemacht haben, implementieren wir unsere erste Komponente.

3. Textfelder hinzufügen

Zuerst fügen wir unserer Anmeldeseite zwei Textfelder hinzu, in die Nutzer ihren Nutzernamen und ihr Passwort eingeben können. Wir verwenden die MDC-Komponente „Textfeld“, die eine integrierte Funktion zum Anzeigen eines unverankerten Labels und von Fehlermeldungen enthält.

d83c47fb4aed3a82.png

XML hinzufügen

Fügen Sie in shr_login_fragment.xml zwei TextInputLayout-Elemente mit einem untergeordneten TextInputEditText in das <LinearLayout> unter dem Label „SHRINE“ <TextView> ein:

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>

Das obige Snippet stellt zwei Textfelder dar, die jeweils aus einem <TextInputLayout> Element und einem <TextInputEditText> untergeordneten Element bestehen. Der Hinweistext für jedes Textfeld wird im Attribut android:hint angegeben.

Wir haben zwei neue String-Ressourcen für das Textfeld hinzugefügt: @string/shr_hint_username und @string/shr_hint_password. Öffnen Sie strings.xml, um diese String-Ressourcen zu sehen.

strings.xml

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

Eingabevalidierung hinzufügen

TextInputLayout-Komponenten bieten eine integrierte Funktion für Fehlerfeedback.

Nehmen Sie die folgenden Änderungen an shr_login_fragment.xml vor, um Fehlerfeedback anzuzeigen:

  • Legen Sie das Attribut app:errorEnabled für das Passwort TextInputLayout-Element auf true fest. Dadurch wird unter dem Textfeld zusätzlicher Abstand für die Fehlermeldung hinzugefügt.
  • Legen Sie das Attribut android:inputType für das Passwort TextInputEditText Element auf "textPassword" fest. Dadurch wird der eingegebene Text im Passwortfeld ausgeblendet.

Nach diesen Änderungen sollten die Textfelder in shr_login_fragment.xml so aussehen:

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>

Führen Sie nun die App aus. Sie sollten eine Seite mit zwei Textfeldern für „Username“ (Nutzername) und „Password“ (Passwort) sehen.

Sehen Sie sich die Animation des unverankerten Labels an:

333184b615aed4f7.gif

4. Schaltflächen hinzufügen

Als Nächstes fügen wir unserer Anmeldeseite zwei Schaltflächen hinzu: „Abbrechen“ und „Weiter“. Wir verwenden die MDC-Komponente „Schaltfläche“, die standardmäßig den typischen Material Design-Tintenwelleneffekt enthält.

4cb0c218948144b4.png

XML hinzufügen

Fügen Sie in shr_login_fragment.xml ein <RelativeLayout> zum <LinearLayout> unter den TextInputLayout Elementen hinzu. Fügen Sie dann dem <RelativeLayout> zwei <MaterialButton>-Elemente hinzu.

Die resultierende XML-Datei sollte so aussehen:

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>

Jetzt weißt du Bescheid. Wenn Sie die App ausführen, wird beim Tippen auf jede Schaltfläche eine Tintenwelle angezeigt.

9dd162d65e4a92a2.gif

5. Zum nächsten Fragment navigieren

Zum Schluss fügen wir LoginFragment.kt etwas Kotlin-Code hinzu, um die Schaltfläche „NEXT“ (Weiter) mit dem Übergang zu einem anderen Fragment zu verknüpfen.

Fügen Sie in LoginFragment.kt unter onCreateView() eine private boolesche Methode isPasswordValid mit Logik hinzu, um zu ermitteln, ob das Passwort gültig ist. Für diese Demo prüfen wir nur, ob das Passwort mindestens 8 Zeichen lang ist:

LoginFragment.kt

private fun isPasswordValid(text: Editable?): Boolean {
   return text != null && text.length >= 8
}

Fügen Sie als Nächstes einen Klick-Listener zur Schaltfläche „Next“ (Weiter) hinzu, der den Fehler basierend auf der gerade erstellten Methode isPasswordValid() festlegt und löscht. In onCreateView(), sollte dieser Klick-Listener zwischen der Inflater-Zeile und der Zeile return view platziert werden.

Fügen Sie nun dem Passwort TextInputEditText einen Key-Listener hinzu, um auf Key-Ereignisse zu warten, die den Fehler löschen. Dieser Listener sollte auch isPasswordValid() verwenden, um zu prüfen, ob das Passwort gültig ist. Sie können ihn direkt unter dem Klick-Listener in onCreateView() hinzufügen.

Ihre Methode „onCreateView()“ sollte nun in etwa so aussehen:

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
   }
}

Jetzt können wir zu einem anderen Fragment navigieren. Aktualisieren Sie in onCreateView() den OnClickListener, um zu einem anderen Fragment zu navigieren, wenn die Fehlerüberprüfung erfolgreich ist. Ihr clickListener-Code sollte jetzt so aussehen:

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

Wir haben dem else-Fall des Klick-Listeners die Zeile (activity as NavigationHost).navigateTo(ProductGridFragment(), false) hinzugefügt. Diese Zeile ruft die Methode navigateTo() aus MainActivity auf, um zu einem neuen Fragment zu navigieren: ProductGridFragment. Derzeit ist dies eine leere Seite, an der Sie in MDC-102 arbeiten.

Erstellen Sie nun die App. Klicken Sie auf die Schaltfläche „Next“ (Weiter).

Geschafft! Dieser Bildschirm ist der Ausgangspunkt für unser nächstes Codelab, an dem Sie in MDC-102 arbeiten.

6. Fertig

Mit grundlegtem XML-Markup und etwa 30 Zeilen Kotlin haben Sie mit der Bibliothek „Material-Komponenten für Android“ eine ansprechende Anmeldeseite erstellt, die den Material Design-Richtlinien entspricht und auf allen Geräten einheitlich aussieht und sich einheitlich verhält.

Weiteres Vorgehen

Das Textfeld und die Schaltfläche sind zwei Kernkomponenten in der MDC Android-Bibliothek, aber es gibt noch viele mehr. Sie können die restlichen Komponenten in MDC Android erkunden. Alternativ können Sie zu MDC 102: Struktur und Layout in Material Design wechseln, um mehr über die obere App-Leiste, die Kartenansicht und das Rasterlayout zu erfahren. Vielen Dank, dass Sie Material-Komponenten ausprobiert haben. Wir hoffen, dieses Codelab hat Ihnen gefallen.

Ich konnte dieses Codelab mit einem angemessenen Zeit- und Arbeitsaufwand abschließen.

Stimme voll und ganz zu Stimme zu Neutral Stimme nicht zu Stimme überhaupt nicht zu

Ich möchte Material-Komponenten auch in Zukunft verwenden.

Stimme voll und ganz zu Stimme zu Neutral Stimme nicht zu Stimme überhaupt nicht zu