1. Einführung
Mit Material Components (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 Components for Android?
Material Design ist ein System zum Erstellen ansprechender und schöner 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 Components for Android (MDC Android) Design und Engineering mit einer Bibliothek von Komponenten, mit denen Sie Ihre Anwendung einheitlich gestalten können. 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 Android-E‑Commerce-App, in der Kleidung und Haushaltswaren verkauft werden. Sie erfahren, wie Sie Komponenten mit MDC Android anpassen können, um eine beliebige Marke oder einen beliebigen Stil widerzuspiegeln.
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“
- Den Namen der App (Shrine)
- Ein Bild des Shrine-Logos

MDC Android-Komponenten in diesem Codelab
- Textfeld
- Schaltfläche
Voraussetzungen
- Grundkenntnisse der Android-Entwicklung
- Android Studio (hier herunterladen, falls noch nicht vorhanden)
- 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?
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 mehrere 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/java.
...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
- Sobald 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). Gehen Sie zu dem Verzeichnis, in dem Sie den Beispielcode installiert haben, und wählen Sie java -> shrine aus (oder suchen Sie auf Ihrem Computer nach shrine), um das Shrine-Projekt zu öffnen.
- Warten Sie einen Moment, bis Android Studio das Projekt erstellt und synchronisiert hat. Dies wird durch Aktivitätsindikatoren unten im Android Studio-Fenster angezeigt.
- An dieser Stelle werden in Android Studio möglicherweise einige Build-Fehler angezeigt, weil das Android SDK oder Build-Tools fehlen, wie im folgenden Beispiel. Folgen Sie der Anleitung in Android Studio, um diese zu installieren oder zu aktualisieren, und synchronisieren Sie Ihr Projekt.
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.
- Gehen Sie zur Datei
build.gradledes Modulsappund prüfen Sie, ob der Blockdependencieseine Abhängigkeit von MDC Android enthält:
api 'com.google.android.material:material:1.1.0-alpha06'
- (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
|
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.

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.java im Verzeichnis shrine -> app -> src -> main -> java -> com.google.codelabs.mdc.java.shrine. Es sollte Folgendes enthalten:
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();
}
}
Diese Aktivität zeigt die Layoutdatei R.layout.shr_main_activity an, die in shr_main_activity.xml definiert ist.
In onCreate(), MainActivity.java startet eine Fragment-Transaktion, um das LoginFragment anzuzeigen. LoginFragment. Das werden wir für dieses Codelab ändern. 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 gehen Sie zur Layoutdatei 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" />
Hier sehen wir ein einfaches <FrameLayout>, das als Container für alle Fragmente dient, die von der Aktivität angezeigt werden. Öffnen wir 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 erweitert die Layoutdatei shr_login_fragment und zeigt sie in onCreateView() an. Sehen wir uns 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" />
<!-- Snippet from "Add text fields" section goes here. -->
<!-- Snippet from "Add buttons" section goes here. -->
</LinearLayout>
</ScrollView>
Hier sehen wir ein <LinearLayout> mit einem <ImageView> oben, das das „Shrine“-Logo darstellt.
Danach folgt ein <TextView>-Tag, das das Label „SHRINE“ 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.
Jetzt, da Sie mit dem Starter-Code vertraut sind, implementieren wir unsere erste Komponente.
3. Textfelder hinzufügen
Zuerst fügen wir unserer Anmeldeseite zwei Textfelder hinzu, in denen Nutzer ihren Nutzernamen und ihr Passwort eingeben können. Wir verwenden die MDC-Komponente „Textfeld“, die eine integrierte Funktion zum Anzeigen eines schwebenden Labels und von Fehlermeldungen enthält.

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"
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>
Das obige Snippet stellt zwei Textfelder dar, die jeweils aus einem <TextInputLayout>-Element und einem untergeordneten <TextInputEditText>-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.
Um Fehlerfeedback anzuzeigen, nehmen Sie die folgenden Änderungen an shr_login_fragment.xml vor:
- Setzen Sie das Attribut
app:errorEnabledfür das PasswortTextInputLayout-Element auf „true“. Dadurch wird unter dem Textfeld zusätzlicher Abstand für die Fehlermeldung hinzugefügt. - Setzen Sie das Attribut
android:inputTypefür das PasswortTextInputEditText-Element auf „textPassword“. 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"
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>
Führen Sie jetzt die App aus. Sie sollten eine Seite mit zwei Textfeldern für „Username“ (Nutzername) und „Password“ (Passwort) sehen.
Sehen Sie sich die Animation des schwebenden Labels an:

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.

XML hinzufügen
Fügen Sie in shr_login_fragment.xml ein <RelativeLayout> zum <LinearLayout> unter den TextInputLayout Elementen hinzu. Fügen Sie dann zwei <MaterialButton>-Elemente zum <RelativeLayout> 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.

5. Zum nächsten Fragment navigieren
Schließlich fügen wir LoginFragment.java etwas Java-Code hinzu, um die Schaltfläche „NEXT“ (Weiter) mit einem anderen Fragment zu verknüpfen. Jeder der Komponenten, die wir unserem Layout hinzugefügt haben, wurde eine id zugewiesen. Wir verwenden diese ids, um auf die Komponenten in unserem Code zu verweisen und Fehlerprüfungen und Navigation hinzuzufügen.
Fügen Sie in LoginFragment.java 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.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;
}
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 als Nächstes 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 jetzt so aussehen:
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;
}
Jetzt können wir zu einem anderen Fragment navigieren. Aktualisieren Sie den OnClickListener in onCreateView(), um zu einem anderen Fragment zu navigieren, wenn die Fehlerüberprüfung erfolgreich ist. Fügen Sie dazu die folgende Zeile hinzu, um zum ProductGridFragment zu navigieren, und zwar zum else-Fall des Klick-Listeners:
LoginFragment.java
...
((NavigationHost) getActivity()).navigateTo(new ProductGridFragment(), false); // Navigate to the next Fragment
...
Ihr Klick-Listener sollte jetzt so aussehen:
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
}
}
});
...
Mit dieser neuen Codezeile wird die Methode navigateTo() aus MainActivity aufgerufen, um zu einem neuen Fragment zu navigieren: ProductGridFragment. Derzeit ist dies eine leere Seite, an der Sie in MDC 102 arbeiten.
Erstellen Sie jetzt die App. Drücken Sie 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 einfachem XML-Markup und etwa 30 Zeilen Java-Code haben Sie mit der Material Components for Android-Bibliothek 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 sich MDC 102: Struktur und Layout in Material Design ansehen, um mehr über die obere App-Leiste, die Kartenansicht und das Rasterlayout zu erfahren. Vielen Dank, dass Sie Material Components ausprobiert haben. Wir hoffen, dieses Codelab hat Ihnen gefallen.