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

logo_components_color_2x_web_96dp.png

Material Components (MDC) helfen Entwicklern bei der Implementierung von Material Design. MDC wurde von einem Team aus Entwicklern und UX-Designern bei Google entwickelt und bietet Dutzende von ansprechenden und funktionalen UI-Komponenten. Es ist für Android, iOS, Web und Flutter verfügbar.

material.io/develop

Im Codelab MDC-101 haben Sie zwei Material Components (MDC) verwendet, um eine Anmeldeseite zu erstellen: Textfelder und Schaltflächen. Jetzt wollen wir diese Grundlage erweitern, indem wir Navigation, Struktur und Daten hinzufügen.

Umfang

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:

  • Eine obere App-Leiste
  • Eine Rasterliste mit Produkten

MDC-Android-Komponenten in diesem Codelab

  • AppBarLayout
  • MaterialCardView

Voraussetzungen

  • Grundkenntnisse in 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ächsten Schritt)

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

Anfänger Mittelstufe Fortgeschritten

Sie machen mit MDC-101 weiter?

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

Sie fangen gerade erst an?

Starter-App für das Codelab herunterladen

Starter-App herunterladen

Die Starter-App befindet sich im Verzeichnis material-components-android-codelabs-102-starter/java. cd Sie vor Beginn in dieses Verzeichnis.

…oder 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. Wenn der Einrichtungsassistent abgeschlossen ist und das Fenster Welcome to Android Studio angezeigt wird, klicken Sie auf Open an existing Android Studio project. Rufen Sie das Verzeichnis auf, 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.
  2. Warten Sie einen Moment, bis Android Studio das Projekt erstellt und synchronisiert hat. Die Aktivitätsanzeigen unten im Android Studio-Fenster geben Aufschluss über den Fortschritt.
  3. An diesem Punkt werden in Android Studio möglicherweise einige Build-Fehler angezeigt, weil das Android SDK oder Build-Tools wie das unten gezeigte fehlen. Folgen Sie der Anleitung in Android Studio, um diese zu installieren/aktualisieren und Ihr Projekt zu synchronisieren.

Projektabhängigkeiten hinzufügen

Das Projekt benötigt eine Abhängigkeit von der MDC Android Support Library. Die heruntergeladenen Beispielcodes sollten diese Abhängigkeit bereits enthalten. 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 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'
}

Start-App ausführen

  1. Achten Sie darauf, dass die Build-Konfiguration links neben der Schaltfläche „Ausführen / Wiedergeben“ app ist.
  2. Klicken Sie auf die grüne Schaltfläche Run / Play (Ausführen / Spielen), um die App zu erstellen und auszuführen.
  3. Wenn im Fenster Select Deployment Target (Bereitstellungsziel auswählen) bereits ein Android-Gerät in der Liste der verfügbaren Geräte 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 Hardware auswählen ein Smartphone aus, z. B. Pixel 2, und klicken Sie dann auf Weiter.
  5. Wählen Sie auf dem Bildschirm System Image (System-Image) eine aktuelle Android-Version aus, vorzugsweise das höchste API-Level. Wenn sie nicht installiert ist, klicken Sie auf den angezeigten Link Herunterladen und schließen Sie den Download ab.
  6. Klicken Sie auf Weiter.
  7. Lassen Sie die Einstellungen auf dem Bildschirm Android Virtual Device (AVD) 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! Sie sollten die Shrine-Anmeldeseite aus dem MDC-101-Codelab sehen.

Nachdem der Anmeldebildschirm nun gut aussieht, füllen wir die App mit einigen Produkten.

Der Startbildschirm wird angezeigt, wenn die Anmeldeseite geschlossen wird. Auf dem Bildschirm wird „Du hast es geschafft!“ angezeigt. Sehr gut. Der Nutzer kann jetzt aber keine Aktionen ausführen und weiß auch nicht, wo er sich in der App befindet. Um das zu ändern, fügen wir die Navigation hinzu.

Material Design bietet Navigationsmuster, die ein hohes Maß an Nutzerfreundlichkeit gewährleisten. Eine der wichtigsten Navigationskomponenten ist die obere App-Leiste.

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

AppBar-Widget hinzufügen

Löschen Sie in shr_product_grid_fragment.xml das <LinearLayout>-Tag mit dem Text „Du hast es geschafft!“. TextView und ersetzen Sie es 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 eine Schaltfläche neben dem Titel. 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 Schaltflächen auf der rechten Seite der App-Leiste hinzufügen. In Android werden diese als Aktionsschaltflächen bezeichnet.

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

Erstellen wir zuerst eine Methode zum Einrichten der Symbolleiste. Die Methode sollte mit id einen Verweis auf die Symbolleiste und mit getActivity() einen Verweis auf die Aktivität abrufen. Wenn die Aktivität nicht null ist, legen Sie die Toolbar fest, die als ActionBar verwendet werden soll, indem Sie setSupportActionBar verwenden:

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 überschreiben wir direkt unter der gerade hinzugefügten setUpToolbar-Methode onCreateOptionsMenu, um den Inhalt von shr_toolbar_menu.xml in die Symbolleiste einzufügen:

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() mit Folgendem hinzugefügt haben:

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 schließlich eine onCreate()-Methode zu ProductGridFragment.java hinzu. Legen Sie im Methodenkörper den Parameter von setHasOptionMenu als true fest.

Die Methode sollte so aussehen:

ProductGridFragment.java

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

Im obigen Code wird die App-Leiste aus unserem XML-Layout als Aktionsleiste für diese Aktivität festgelegt. Der Callback onCreateOptionsMenu teilt der Aktivität mit, welches Menü verwendet werden soll. In diesem Fall werden die Menüelemente aus R.menu.shr_toolbar_menu in die App-Leiste eingefügt.

Die Menüdatei enthält zwei Elemente: „Suchen“ und „Filtern“.

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 so aussehen:

Die Symbolleiste enthält jetzt ein Navigationssymbol, einen Titel und zwei Aktionssymbole auf der rechten Seite. Die Symbolleiste wird auch durch einen dezenten Schatten hervorgehoben, der zeigt, dass sie sich auf einer anderen Ebene als die Inhalte befindet.

Nachdem wir unserer App eine Struktur gegeben haben, organisieren wir die Inhalte, indem wir sie in Karten platzieren.

Karte hinzufügen

Fügen wir zuerst 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:

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

Sie können einem Container die folgenden Elemente hinzufügen: Überschrift, Thumbnail oder Avatar, Unterüberschrift, Trennzeichen sowie Schaltflächen und Symbole. Die gerade erstellte Karte enthält beispielsweise zwei TextView-Elemente (eines für den Titel und eines für den sekundären Text) in einem LinearLayout-Element, das am unteren Rand der Karte ausgerichtet ist.

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

Wenn auf einem Bildschirm mehrere Karten vorhanden sind, werden sie in einer oder mehreren Sammlungen gruppiert. Karten in einem Raster sind koplanar. Das bedeutet, dass sie alle auf derselben Höhe liegen, sofern sie nicht aufgenommen oder gezogen werden. Das wird in diesem Codelab jedoch nicht behandelt.

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 wir Bilder aus einer URL einfügen können) und zwei TextViews.

Sehen Sie sich als Nächstes die ProductCardRecyclerViewAdapter an, die wir für Sie bereitgestellt haben. Sie 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 den Inhalt unseres Rasters. Um festzulegen, was mit den jeweiligen Inhalten in den einzelnen Ansichten geschehen soll, schreiben wir bald den Code für onBindViewHolder().

Im selben Paket finden Sie auch ProductCardViewHolder. In dieser Klasse werden die Ansichten gespeichert, die sich auf unser 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 das Raster einzurichten, entfernen wir zuerst den Platzhalter MaterialCardView aus shr_product_grid_fragment.xml. Als Nächstes fügen Sie die Komponente hinzu, die das Raster mit den Karten darstellt. Fügen Sie in diesem Fall unter der XML-Komponente AppBarLayout eine RecyclerView-Komponente zu Ihrem shr_product_grid_fragment.xml 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>

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>

   <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 schließlich in onCreateView() den RecyclerView-Initialisierungscode in ProductGridFragment.java ein, nachdem Sie setUpToolbar(view) aufgerufen haben und vor der return-Anweisung:

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 eines RecyclerView. Dazu gehört das Festlegen des Layoutmanagers für RecyclerView sowie das Initialisieren und Festlegen des Adapters für 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

Die Karten sind jetzt da. Bisher wird noch nichts angezeigt. Fügen wir also einige Produktdaten hinzu.

Bilder und Text hinzufügen

Fügen Sie für jede Karte ein Bild, einen Produktnamen und einen Preis hinzu. In unserer ViewHolder-Abstraktion sind die Aufrufe für jede Karte enthalten. Fügen Sie in ViewHolder die drei Ansichten wie folgt 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 von RecyclerView in ViewHolder, die Methode onBindViewHolder(), 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 von RecyclerView mit einem ViewHolder mitgeteilt, was mit den einzelnen Karten geschehen soll.

Hier werden die Textdaten für die einzelnen ViewHolder-TextViews festgelegt und ein ImageRequester aufgerufen, um ein Bild von einer URL abzurufen. Die ImageRequester-Klasse haben wir für Sie bereitgestellt. Sie verwendet die Volley-Bibliothek. Das ist ein Thema, das über den Rahmen dieses Codelabs hinausgeht. Sie können sich den Code aber gern selbst ansehen.

Erstellen und ausführen:

Unsere Produkte werden jetzt in der App angezeigt.

Unsere App hat einen einfachen Ablauf, der den Nutzer vom Anmeldebildschirm zu einem Startbildschirm führt, auf dem Produkte angezeigt werden. Mit nur wenigen Zeilen Code haben wir eine obere App-Leiste mit einem Titel und drei Schaltflächen sowie ein Raster mit Karten zum Präsentieren der Inhalte unserer App hinzugefügt. Unser Startbildschirm ist jetzt einfach und funktional, mit einer grundlegenden Struktur und umsetzbaren Inhalten.

Weiteres Vorgehen

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

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

Ich konnte dieses Codelab mit einem angemessenen Zeit- und Arbeitsaufwand durcharbeiten.

Stimme vollkommen zu Stimme zu Neutral Stimme nicht zu Stimme überhaupt nicht zu

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

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