MDC-102 Android: Material Structure and Layout (Java)

1. Einführung

logo_components_color_2x_web_96dp.png

Material Components (MDC) unterstützen Entwickler bei der Implementierung von Material Design. MDC wurde von einem Team aus Entwicklern und UX-Designern bei Google entwickelt. Es enthält Dutzende schöne und funktionale UI-Komponenten und ist für Android, iOS, das Web und Flutter.material.io/develop verfügbar.

Im Codelab MDC-101 haben Sie zwei Material Components (MDC) zum Erstellen einer Anmeldeseite verwendet: Textfelder und Schaltflächen. Erweitern wir diese Grundlage nun um Navigation, Struktur und Daten.

Inhalt

In diesem Codelab erstellen Sie einen Startbildschirm für die App Shrine, eine E-Commerce-App, in der Kleidung und Haushaltswaren verkauft werden. Sie enthält Folgendes:

  • Obere App-Leiste
  • Eine Rasterliste mit Produkten

249db074eff043f4.png

MDC-Android-Komponenten in diesem Codelab

  • AppBarLayout
  • MaterialCardView

Voraussetzungen

  • Grundkenntnisse in der Android-Entwicklung
  • Android Studio (hier herunterladen, falls Sie es noch nicht haben)
  • Einen Android-Emulator oder ein Android-Gerät (über Android Studio verfügbar)
  • Beispielcode (siehe nächster Schritt)

Wie würden Sie Ihre Erfahrung im Erstellen von Android-Apps bewerten?

Anfänger Mittelstufe Fortgeschritten

2. Entwicklungsumgebung einrichten

Sind Sie nach MDC-101 weitergegangen?

Wenn du MDC-101 abgeschlossen hast, sollte dein Code für dieses Codelab bereit sein. Sie können mit Schritt 3 fortfahren: Obere App-Leiste hinzufügen.

Sie beginnen ganz neu?

Starter-Codelab-App herunterladen

Die Starter-App befindet sich im Verzeichnis material-components-android-codelabs-102-starter/java. Sie müssen sich vor Beginn in diesem Verzeichnis cd befinden.

…oder es aus GitHub klonen

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

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

Startcode in Android Studio laden

  1. Sobald der Einrichtungsassistent fertig ist und das Fenster Willkommen bei Android Studio angezeigt wird, klicken Sie auf Vorhandenes Android Studio-Projekt öffnen. Gehen Sie zu dem Verzeichnis, in dem Sie den Beispielcode installiert haben, und wählen Sie java -> shared aus oder suchen Sie auf Ihrem Computer nach shrine, um das Shrine-Projekt zu öffnen.
  2. Warten Sie einen Moment, bis Android Studio das Projekt erstellt und synchronisiert hat. Das wird durch Aktivitätssymbole am unteren Rand des Android Studio-Fensters angezeigt.
  3. An dieser Stelle kann Android Studio einige Build-Fehler ausgeben, weil das Android SDK oder die Build-Tools (siehe unten) fehlen. Folgen Sie der Anleitung in Android Studio, um diese zu installieren bzw. zu aktualisieren und Ihr Projekt zu synchronisieren.

F5H6srsw_5xOPGFpKrm1RwgewatxA_HUbDI1PWoQUAoJcT6DpfBOkAYwq3S-2vUHvweUaFgAmG7BtUKkGouUbhTwXQh53qec8tO5eVecdlo7QIoLc8rNxFEBb8l7RlS-KzBbZOzVhA

Projektabhängigkeiten hinzufügen

Das Projekt benötigt eine Abhängigkeit von der MDC Android-Supportbibliothek. Im Beispielcode, den Sie heruntergeladen haben, sollte diese Abhängigkeit bereits aufgeführt sein. Es empfiehlt sich jedoch, die folgenden Schritte durchzufü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 synchronisieren Sie das Projekt.
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. Die Build-Konfiguration links neben der Schaltfläche Ausführen/Wiedergeben muss app sein.
  2. Klicken Sie auf die grüne Schaltfläche Run / Play, um die App zu erstellen und auszuführen.
  3. Wenn im Fenster Bereitstellungsziel auswählen bereits ein Android-Gerät in den verfügbaren Geräten aufgeführt ist, fahren Sie mit Schritt 8 fort. Klicken Sie andernfalls auf Neues virtuelles Gerät erstellen.
  4. Wählen Sie auf dem Bildschirm Hardware auswählen ein Smartphone wie Pixel 2 aus und klicken Sie dann auf Weiter.
  5. Wählen Sie auf dem Bildschirm System-Image die aktuelle Android-Version aus, vorzugsweise die höchste API-Ebene. Wenn die App nicht installiert ist, klicken Sie auf den angezeigten Link Herunterladen und führen Sie den Download aus.
  6. Klicken Sie auf Weiter.
  7. Lassen Sie auf dem Bildschirm Android Virtual Device (AVD) die Einstellungen unverändert und klicken Sie auf Fertigstellen.
  8. Wählen Sie im Dialogfeld „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! Die Anmeldeseite von Shrine im Codelab „MDC-101“ sollte angezeigt werden.

4cb0c218948144b4.png

Jetzt, da der Anmeldebildschirm fertig ist, füllen wir die App mit einigen Produkten.

3. App-Leiste oben hinzufügen

Der Startbildschirm wird angezeigt, wenn die Anmeldeseite geschlossen wird. Der Bildschirm zeigt die Meldung „Du hast es geschafft!“. Sehr gut. Jetzt hat der Nutzer jedoch keine Aktionen mehr zu tun und weiß auch nicht, wo er sich in der App befindet. Um ihm dabei zu helfen, fügen wir die Navigation hinzu.

Material Design bietet Navigationsmuster, die für eine hohe Nutzerfreundlichkeit sorgen. Eine der bemerkenswertesten Navigationskomponenten ist die obere App-Leiste.

Fügen wir eine App-Leiste oben hinzu, um die Navigation zu ermöglichen und Nutzern schnellen Zugriff auf andere Aktionen zu geben.

AppBar-Widget hinzufügen

Löschen Sie in shr_product_grid_fragment.xml das <LinearLayout>-Tag mit der Meldung „Du hast es geschafft! TextView und ersetzen Sie ihn durch Folgendes:

shr_product_grid_fragment.xml

<com.google.android.material.appbar.AppBarLayout
   android:layout_width="match_parent"
   android:layout_height="wrap_content">

   <androidx.appcompat.widget.Toolbar
       android:id="@+id/app_bar"
       style="@style/Widget.Shrine.Toolbar"
       android:layout_width="match_parent"
       android:layout_height="?attr/actionBarSize"
       app:title="@string/shr_app_name" />
</com.google.android.material.appbar.AppBarLayout>

Ihr shr_product_grid_fragment.xml sollte so aussehen:

shr_product_grid_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
   tools:context=".ProductGridFragment">

   <com.google.android.material.appbar.AppBarLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content">

       <androidx.appcompat.widget.Toolbar
           android:id="@+id/app_bar"
           style="@style/Widget.Shrine.Toolbar"
           android:layout_width="match_parent"
           android:layout_height="?attr/actionBarSize"
           app:title="@string/shr_app_name" />
   </com.google.android.material.appbar.AppBarLayout>
  
</FrameLayout>

Viele App-Leisten haben neben dem Titel eine Schaltfläche. Fügen wir unserem Menü ein Menüsymbol hinzu.

Navigationssymbol hinzufügen

Fügen Sie in shr_product_grid_fragment.xml der XML-Komponente Toolbar, die Sie gerade Ihrem Layout hinzugefügt haben, Folgendes hinzu:

shr_product_grid_fragment.xml

app:navigationIcon="@drawable/shr_menu"

Ihr shr_product_grid_fragment.xml sollte so aussehen:

shr_product_grid_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
   tools:context=".ProductGridFragment">
  
   <com.google.android.material.appbar.AppBarLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content">

       <androidx.appcompat.widget.Toolbar
           android:id="@+id/app_bar"
           style="@style/Widget.Shrine.Toolbar"
           android:layout_width="match_parent"
           android:layout_height="?attr/actionBarSize"
           app:navigationIcon="@drawable/shr_menu"
           app:title="@string/shr_app_name" />
   </com.google.android.material.appbar.AppBarLayout>
  
</FrameLayout>

Aktionsschaltflächen hinzufügen und die obere App-Leiste gestalten

Sie können auch am Ende der App-Leiste Schaltflächen hinzufügen. In Android werden diese Schaltflächen als Aktionsschaltflächen bezeichnet.

Wir gestalten die obere App-Leiste und fügen dem Menü programmatisch Aktionsschaltflächen hinzu.

Zunächst erstellen wir eine Methode zum Einrichten der Toolbar. Die Methode sollte über id eine Referenz auf die Symbolleiste und über getActivity() eine Referenz auf die Aktivität abrufen. Wenn die Aktivität nicht null ist, legen Sie mit setSupportActionBar fest, dass Toolbar als ActionBar verwendet werden soll:

ProductGridFragment.java

private void setUpToolbar(View view) {
   Toolbar toolbar = view.findViewById(R.id.app_bar);
   AppCompatActivity activity = (AppCompatActivity) getActivity();
   if (activity != null) {
       activity.setSupportActionBar(toolbar);
   }
}

Als Nächstes wird direkt unter der soeben hinzugefügten setUpToolbar-Methode onCreateOptionsMenu überschrieben, um den Inhalt von shr_toolbar_menu.xml in der Symbolleiste zu maximieren:

ProductGridFragment.java

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
   menuInflater.inflate(R.menu.shr_toolbar_menu, menu);
   super.onCreateOptionsMenu(menu, menuInflater);
}

Fügen Sie nun einen Aufruf der Methode setUpToolbar hinzu, die wir dem Inhalt der Methode onCreateView() hinzugefügt haben, und zwar mit folgendem Code:

ProductGridFragment.java

@Override
public View onCreateView(
       @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
   // Inflate the layout for this fragment with the ProductGrid theme
   View view = inflater.inflate(R.layout.shr_product_grid_fragment, container, false);

   // Set up the toolbar
   setUpToolbar(view);

   return view;
}

Fügen Sie ProductGridFragment.java abschließend eine onCreate()-Methode hinzu. Legen Sie im Methodentext den Parameter von setHasOptionMenu auf true fest.

Die Methode sollte so aussehen:

ProductGridFragment.java

@Override
public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setHasOptionsMenu(true);
}

Mit dem Code oben wird die App-Leiste aus unserem XML-Layout als Aktionsleiste für diese Aktivität festgelegt. Der Callback onCreateOptionsMenu teilt der Aktivität mit, was als Menü verwendet werden soll. In diesem Fall werden die Menüpunkte von R.menu.shr_toolbar_menu in der App-Leiste platziert.

Die Menüdatei enthält zwei Elemente: „Search“ und „Filter“.

shr_toolbar_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto">
   <item
       android:id="@+id/search"
       android:icon="@drawable/shr_search"
       android:title="@string/shr_search_title"
       app:showAsAction="always" />
   <item
       android:id="@+id/filter"
       android:icon="@drawable/shr_filter"
       android:title="@string/shr_filter_title"
       app:showAsAction="always" />
</menu>

Nach diesen Änderungen sollte Ihre ProductGridFragment.java-Datei so aussehen:

ProductGridFragment.java

package com.google.codelabs.mdc.java.shrine;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toolbar;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;


public class ProductGridFragment extends Fragment {

   @Override
   public void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setHasOptionsMenu(true);
   }
  
   @Override
   public View onCreateView(
           @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
       // Inflate the layout for this fragment with the ProductGrid theme
       View view = inflater.inflate(R.layout.shr_product_grid_fragment, container, false);

       // Set up the toolbar
       setUpToolbar(view);

       return view;
   }
  
   private void setUpToolbar(View view) {
       Toolbar toolbar = view.findViewById(R.id.app_bar);
       AppCompatActivity activity = (AppCompatActivity) getActivity();
       if (activity != null) {
           activity.setSupportActionBar(toolbar);
       }
   }

   @Override
   public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
       menuInflater.inflate(R.menu.shr_toolbar_menu, menu);
       super.onCreateOptionsMenu(menu, menuInflater);
   }

}

Erstellen und ausführen. Ihr Startbildschirm sollte nun so aussehen:

d04e8aa3b27f4754.png

Die Symbolleiste enthält jetzt auf der rechten Seite ein Navigationssymbol, einen Titel und zwei Aktionssymbole. Die Symbolleiste zeigt auch Höhendaten mit einem dezenten Schatten an, der darauf hinweist, dass sich die Ebene auf einer anderen Ebene als der Inhalt befindet.

4. Karte hinzufügen

Unsere App hat jetzt eine gewisse Struktur. Organisieren Sie die Inhalte, indem Sie sie in Karten platzieren.

Karte hinzufügen

Fügen wir zunächst eine Karte unter der oberen App-Leiste hinzu. Eine Karte sollte einen Bereich für ein Bild, einen Titel und ein Label für sekundären Text haben.

Fügen Sie in shr_product_grid_fragment.xml unter AppBarLayout Folgendes hinzu:

shr_product_grid_fragment.xml

<com.google.android.material.card.MaterialCardView
   android:layout_width="160dp"
   android:layout_height="180dp"
   android:layout_marginBottom="16dp"
   android:layout_marginLeft="16dp"
   android:layout_marginRight="16dp"
   android:layout_marginTop="70dp"
   app:cardBackgroundColor="?attr/colorPrimaryDark"
   app:cardCornerRadius="4dp">

   <LinearLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:layout_gravity="bottom"
       android:background="#FFFFFF"
       android:orientation="vertical"
       android:padding="8dp">

       <TextView
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:padding="2dp"
           android:text="@string/shr_product_title"
           android:textAppearance="?attr/textAppearanceHeadline6" />

       <TextView
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:padding="2dp"
           android:text="@string/shr_product_description"
           android:textAppearance="?attr/textAppearanceBody2" />
   </LinearLayout>
</com.google.android.material.card.MaterialCardView>

Erstellen und ausführen:

f6184a55ccb5f920.png

In dieser Vorschau sehen Sie, dass die Karte vom linken Bildschirmrand eingerückt ist. Außerdem hat sie abgerundete Ecken und einen Schatten, der die Höhe der Karte darstellt. Der gesamte Bereich wird als „Container“ bezeichnet. Abgesehen vom Container selbst sind alle darin enthaltenen Elemente optional.

Sie können einem Container folgende Elemente hinzufügen: Überschrift, Miniaturansicht oder Avatar, Zwischenüberschrift, Trennlinien und sogar Schaltflächen und Symbole. Die soeben erstellte Karte enthält beispielsweise zwei TextViews (eines für den Titel und eine für sekundären Text) in einem LinearLayout, die am unteren Rand der Karte ausgerichtet sind.

Karten werden normalerweise zusammen mit anderen Karten in einer Sammlung angezeigt. Im nächsten Abschnitt dieses Codelabs ordnen wir sie als Sammlung in einem Raster an.

5. Kartenraster erstellen

Wenn sich auf einem Bildschirm mehrere Karten befinden, werden sie in einer oder mehreren Sammlungen gruppiert. Karten in einem Raster liegen in einer Ebene, d. h., sie haben dieselbe Ruhehöhe wie die anderen Karten (es sei denn, sie werden aufgehoben oder verschoben, was in diesem Codelab jedoch nicht behandelt wird).

Kartenraster einrichten

Sehen Sie sich die Datei shr_product_card.xml an, die wir für Sie bereitgestellt haben:

shr_product_card.xml

<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   app:cardBackgroundColor="@android:color/white"
   app:cardElevation="2dp"
   app:cardPreventCornerOverlap="true">

   <LinearLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:orientation="vertical">

       <com.android.volley.toolbox.NetworkImageView
           android:id="@+id/product_image"
           android:layout_width="match_parent"
           android:layout_height="@dimen/shr_product_card_image_height"
           android:background="?attr/colorPrimaryDark"
           android:scaleType="centerCrop" />

       <LinearLayout
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:orientation="vertical"
           android:padding="16dp">

           <TextView
               android:id="@+id/product_title"
               android:layout_width="match_parent"
               android:layout_height="wrap_content"
               android:text="@string/shr_product_title"
               android:textAppearance="?attr/textAppearanceHeadline6" />

           <TextView
               android:id="@+id/product_price"
               android:layout_width="match_parent"
               android:layout_height="wrap_content"
               android:text="@string/shr_product_description"
               android:textAppearance="?attr/textAppearanceBody2" />
       </LinearLayout>
   </LinearLayout>
</com.google.android.material.card.MaterialCardView>

Dieses Kartenlayout enthält eine Karte mit einem Bild (hier ein NetworkImageView, mit dem Bilder von einer URL eingefügt werden können) und zwei TextViews.

Sehen Sie sich als Nächstes die von uns bereitgestellte ProductCardRecyclerViewAdapter an. Es befindet sich im selben Paket wie ProductGridFragment.

ProductCardRecyclerViewAdapter.java

package com.google.codelabs.mdc.java.shrine;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import com.google.codelabs.mdc.java.shrine.network.ImageRequester;
import com.google.codelabs.mdc.java.shrine.network.ProductEntry;

import java.util.List;

/**
* Adapter used to show a simple grid of products.
*/
public class ProductCardRecyclerViewAdapter extends RecyclerView.Adapter<ProductCardViewHolder> {

   private List<ProductEntry> productList;
   private ImageRequester imageRequester;

   ProductCardRecyclerViewAdapter(List<ProductEntry> productList) {
       this.productList = productList;
       imageRequester = ImageRequester.getInstance();
   }

   @NonNull
   @Override
   public ProductCardViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
       View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.shr_product_card, parent, false);
       return new ProductCardViewHolder(layoutView);
   }

   @Override
   public void onBindViewHolder(@NonNull ProductCardViewHolder holder, int position) {
       // TODO: Put ViewHolder binding code here in MDC-102
   }

   @Override
   public int getItemCount() {
       return productList.size();
   }
}

Die Adapterklasse oben verwaltet die Inhalte unseres Rasters. Um festzulegen, was jede Ansicht mit dem jeweiligen Inhalt tun soll, schreiben wir demnächst den Code für onBindViewHolder().

Im selben Paket kannst du dir auch ProductCardViewHolder ansehen. In dieser Klasse werden die Ansichten gespeichert, die sich auf das Kartenlayout auswirken, damit wir sie später ändern können.

ProductCardViewHolder.java

package com.google.codelabs.mdc.java.shrine;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import android.view.View;

public class ProductCardViewHolder extends RecyclerView.ViewHolder {

   public ProductCardViewHolder(@NonNull View itemView) {
       super(itemView);
       // TODO: Find and store views from itemView
   }
}

Um unser Raster einzurichten, entfernen wir zuerst den Platzhalter MaterialCardView aus shr_product_grid_fragment.xml. Als Nächstes sollten Sie die Komponente hinzufügen, die unser Kartenraster darstellt. Fügen Sie in diesem Fall unter shr_product_grid_fragment.xml unter der XML-Komponente AppBarLayout eine RecyclerView-Komponente hinzu:

shr_product_grid_fragment.xml

<androidx.core.widget.NestedScrollView
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:layout_marginTop="56dp"
   android:background="@color/productGridBackgroundColor"
   android:paddingStart="@dimen/shr_product_grid_spacing"
   android:paddingEnd="@dimen/shr_product_grid_spacing"
   app:layout_behavior="@string/appbar_scrolling_view_behavior">

   <androidx.recyclerview.widget.RecyclerView
       android:id="@+id/recycler_view"
       android:layout_width="match_parent"
       android:layout_height="match_parent" />

</androidx.core.widget.NestedScrollView>

Ihre shr_product_grid_fragment.xml sollte so aussehen:

shr_product_grid_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
   tools:context=".ProductGridFragment">

   <com.google.android.material.appbar.AppBarLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content">

       <androidx.appcompat.widget.Toolbar
           android:id="@+id/app_bar"
           style="@style/Widget.Shrine.Toolbar"
           android:layout_width="match_parent"
           android:layout_height="?attr/actionBarSize"
           app:navigationIcon="@drawable/shr_menu"
           app:title="@string/shr_app_name" />
   </com.google.android.material.appbar.AppBarLayout>

   <androidx.core.widget.NestedScrollView
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:layout_marginTop="56dp"
       android:background="@color/productGridBackgroundColor"
       android:paddingStart="@dimen/shr_product_grid_spacing"
       android:paddingEnd="@dimen/shr_product_grid_spacing"
       app:layout_behavior="@string/appbar_scrolling_view_behavior">

       <androidx.recyclerview.widget.RecyclerView
           android:id="@+id/recycler_view"
           android:layout_width="match_parent"
           android:layout_height="match_parent" />

   </androidx.core.widget.NestedScrollView>

</FrameLayout>

Fügen Sie in onCreateView() den RecyclerView-Initialisierungscode in ProductGridFragment.java ein, nachdem Sie setUpToolbar(view) aufgerufen und vor der return-Anweisung platziert haben:

ProductGridFragment.java

@Override
public View onCreateView(
       @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
   ...
   setUpToolbar(view);

   // Set up the RecyclerView
   RecyclerView recyclerView = view.findViewById(R.id.recycler_view);
   recyclerView.setHasFixedSize(true);
   recyclerView.setLayoutManager(new GridLayoutManager(getContext(), 2, GridLayoutManager.VERTICAL, false));
   ProductCardRecyclerViewAdapter adapter = new ProductCardRecyclerViewAdapter(
           ProductEntry.initProductEntryList(getResources()));
   recyclerView.setAdapter(adapter);
   int largePadding = getResources().getDimensionPixelSize(R.dimen.shr_product_grid_spacing);
   int smallPadding = getResources().getDimensionPixelSize(R.dimen.shr_product_grid_spacing_small);
   recyclerView.addItemDecoration(new ProductGridItemDecoration(largePadding, smallPadding));

   return view;
}

Das obige Code-Snippet enthält die erforderlichen Initialisierungsschritte zum Einrichten von RecyclerView. Dazu gehört das Festlegen des Layout-Managers von RecyclerView sowie das Initialisieren und Einrichten des Adapters von RecyclerView.

Ihre ProductGridFragment.java-Datei sollte jetzt so aussehen:

ProductGridFragment.java

package com.google.codelabs.mdc.java.shrine;

import android.os.Bundle;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toolbar;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.GridLayoutManager;


import com.google.codelabs.mdc.java.shrine.network.ProductEntry;

public class ProductGridFragment extends Fragment {

   @Override
   public void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setHasOptionsMenu(true);
   }

   @Override
   public View onCreateView(
           @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
       // Inflate the layout for this fragment with the ProductGrid theme
       View view = inflater.inflate(R.layout.shr_product_grid_fragment, container, false);

       // Set up the toolbar
       setUpToolbar(view);

       // Set up the RecyclerView
       RecyclerView recyclerView = view.findViewById(R.id.recycler_view);
       recyclerView.setHasFixedSize(true);
       recyclerView.setLayoutManager(new GridLayoutManager(getContext(), 2, GridLayoutManager.VERTICAL, false));
       ProductCardRecyclerViewAdapter adapter = new ProductCardRecyclerViewAdapter(
               ProductEntry.initProductEntryList(getResources()));
       recyclerView.setAdapter(adapter);
       int largePadding = getResources().getDimensionPixelSize(R.dimen.shr_product_grid_spacing);
       int smallPadding = getResources().getDimensionPixelSize(R.dimen.shr_product_grid_spacing_small);
       recyclerView.addItemDecoration(new ProductGridItemDecoration(largePadding, smallPadding));

       return view;
   }

   private void setUpToolbar(View view) {
       Toolbar toolbar = view.findViewById(R.id.app_bar);
       AppCompatActivity activity = (AppCompatActivity) getActivity();
       if (activity != null) {
           activity.setSupportActionBar(toolbar);
       }
   }

   @Override
   public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
       menuInflater.inflate(R.menu.shr_toolbar_menu, menu);
       super.onCreateOptionsMenu(menu, menuInflater);
   }

}

Erstellen und ausführen.

f9aeab846fc3bb4c.png

Die Karten sind da! Es werden noch nichts angezeigt, also lassen Sie uns einige Produktdaten hinzufügen.

Bilder und Text hinzufügen

Fügen Sie jeder Karte ein Bild, einen Produktnamen und einen Preis hinzu. Die ViewHolder-Abstraktion enthält die Aufrufe für jede Karte. Fügen Sie in der ViewHolder die drei Ansichten so hinzu:

ProductCardViewHolder.java

package com.google.codelabs.mdc.java.shrine;

import androidx.recyclerview.widget.RecyclerView;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.NonNull;

import com.android.volley.toolbox.NetworkImageView;

public class ProductCardViewHolder extends RecyclerView.ViewHolder {

   public NetworkImageView productImage;
   public TextView productTitle;
   public TextView productPrice;

   public ProductCardViewHolder(@NonNull View itemView) {
       super(itemView);
       productImage = itemView.findViewById(R.id.product_image);
       productTitle = itemView.findViewById(R.id.product_title);
       productPrice = itemView.findViewById(R.id.product_price);
   }
}

Aktualisieren Sie im Adapter des RecyclerView in der ViewHolder, die onBindViewHolder()-Methode, um die Informationen für jede Ansicht festzulegen:

ProductCardRecyclerViewAdapter.java

@Override
public void onBindViewHolder(@NonNull ProductCardViewHolder holder, int position) {
   if (productList != null && position < productList.size()) {
       ProductEntry product = productList.get(position);
       holder.productTitle.setText(product.title);
       holder.productPrice.setText(product.price);
       imageRequester.setImageFromUrl(holder.productImage, product.url);
   }
}

Im obigen Code wird dem Adapter unserer RecyclerView mithilfe einer ViewHolder mitgeteilt, was mit jeder Karte zu tun ist.

Hier werden die Textdaten für alle TextViews der ViewHolder festgelegt und eine ImageRequester aufgerufen, um ein Bild über eine URL abzurufen. Die ImageRequester ist eine Klasse, die wir für Sie bereitgestellt haben. Sie verwendet die Volley-Bibliothek. Dieses Thema fällt nicht in den Rahmen dieses Codelabs, aber Sie können sich den Code gern selbst ansehen.

Erstellen und ausführen:

249db074eff043f4.png

Unsere Produkte werden jetzt in der App angezeigt.

6. Zusammenfassung

Unsere App hat einen grundlegenden Ablauf, der den Nutzer vom Anmeldebildschirm zu einem Startbildschirm bringt, auf dem die Produkte angezeigt werden können. Mit nur wenigen Codezeilen haben wir eine obere App-Leiste mit einem Titel und drei Schaltflächen sowie ein Kartenraster hinzugefügt, um die Inhalte unserer App zu präsentieren. Der Startbildschirm ist jetzt einfach und funktional, mit einer einfachen Struktur und umsetzbaren Inhalten.

Weiteres Vorgehen

Mit der oberen App-Leiste, der Karte, dem Textfeld und der Schaltfläche haben wir jetzt vier Hauptkomponenten von Material Design aus der MDC-Android-Bibliothek verwendet. Weitere Komponenten finden Sie im MDC-Android-Katalog unter Komponenten in MDC Android.

Unsere App ist zwar voll funktionsfähig, repräsentiert aber noch keine bestimmte Marke. In MDC-103: Material Design Theming with Color, Shape, Elevation and Type passen wir den Stil dieser Komponenten an, um eine lebendige, moderne Marke auszudrücken.

Ich konnte dieses Codelab mit angemessenem Zeitaufwand und Mühe abschließen.

Stimme voll zu Stimme zu Neutral Stimme nicht zu Stimme überhaupt nicht zu

Ich möchte Material Components weiterhin verwenden.

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