MDC-102 Android: struktura i układ materiału (Java)

1. Wprowadzenie

logo_components_color_2x_web_96dp.png

Material Komponenty (MDC) pomagają deweloperom wdrażać interfejs Material Design. MDC, stworzony przez zespół inżynierów i projektantów UX w Google, obejmuje dziesiątki pięknych i funkcjonalnych komponentów interfejsu. Jest dostępny na Androida, iOS, internet i Flutter.material.io/develop

W ramach ćwiczenia w Codelabs w wersji MDC-101 do stworzenia strony logowania: pól tekstowych i przycisków, wykorzystano 2 komponenty Material Komponenty (MDC). Rozwińmy te podstawy, dodając nawigację, strukturę i dane.

Co utworzysz

W ramach tego ćwiczenia w Codelabs utworzysz ekran główny aplikacji o nazwie Shrine – aplikacji e-commerce, która umożliwia sprzedaż odzieży i artykułów wyposażenia domu. Będą one zawierać:

  • Pasek aplikacji u góry
  • Siatka z produktami

249db074eff043f4.png

komponenty MDC-Android w tym ćwiczeniu w Codelabs

  • AppBarLayout
  • MaterialCardView

Czego potrzebujesz

  • podstawowa wiedza o programowaniu aplikacji na Androida;
  • Android Studio (pobierz tę aplikację stąd, jeśli jeszcze jej nie masz)
  • emulator lub urządzenie z Androidem (dostępne w Android Studio).
  • Przykładowy kod (patrz następny krok)

Jak oceniasz swój poziom doświadczenia w tworzeniu aplikacji na Androida?

Początkujący Średnio zaawansowany Zaawansowany

2. Konfigurowanie środowiska programistycznego

Czy kontynuujesz na podstawie szkolenia MDC-101?

Jeśli masz ukończony kod MDC-101, Twój kod powinien być gotowy do tego ćwiczenia z programowania. Możesz przejść do kroku 3. Dodaj górny pasek aplikacji.

Zaczynasz od zera?

Pobierz aplikację startową z programowania

Aplikacja startowa znajduje się w katalogu material-components-android-codelabs-102-starter/java. Zanim zaczniesz, przejdź do tego katalogu.

...lub skopiuj je z GitHuba

Aby skopiować to ćwiczenia z programowania z GitHuba, uruchom te polecenia:

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

Wczytaj kod startowy w Android Studio

  1. Gdy kreator konfiguracji zakończy działanie i pojawi się okno Witamy w Android Studio, kliknij Otwórz istniejący projekt Android Studio. Przejdź do katalogu, w którym został zainstalowany przykładowy kod, i wybierz java -> Temple (lub wyszukaj na komputerze shrine), aby otworzyć projekt Shrine.
  2. Poczekaj, aż Android Studio skompiluje i zsynchronizuje projekt, zgodnie ze wskaźnikami aktywności u dołu okna Android Studio.
  3. W tym momencie Android Studio może wyświetlić błędy kompilacji, ponieważ brakuje pakietu Android SDK lub narzędzi do kompilacji, takich jak pokazane poniżej. Postępuj zgodnie z instrukcjami w Android Studio, aby zainstalować lub zaktualizować te aplikacje i zsynchronizować projekt.

F5H6srsw_5xOPGFpKrm1RwgewatxA_HUbDI1PWoQUAoJcT6DpfBOkAYwq3S-2vUHvweUaFgAmG7BtUKkGouUbhTwXQh53qec8tO5eVecdlo7QIoLc8rNxFEBb8l7RlS-KzBbZOzVhA

Dodaj zależności projektu

Projekt musi być zależny od biblioteki pomocy MDC Android. Pobierany przez Ciebie przykładowy kod powinien już zawierać tę zależność, ale aby się o tym przekonać, wykonaj te czynności.

  1. Przejdź do pliku build.gradle modułu app i upewnij się, że blok dependencies zawiera zależność od MDC na Androidzie:
api 'com.google.android.material:material:1.1.0-alpha06'
  1. (Opcjonalnie) W razie potrzeby zmodyfikuj plik build.gradle, aby dodać poniższe zależności i zsynchronizować 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'
}

Uruchomienie aplikacji startowej

  1. Upewnij się, że konfiguracja kompilacji po lewej stronie przycisku Uruchom/Odtwórz to app.
  2. Aby skompilować i uruchomić aplikację, kliknij zielony przycisk Uruchom / Odtwórz.
  3. Jeśli masz już urządzenie z Androidem na liście dostępnych urządzeń, w oknie Wybierz cel wdrożenia przejdź do kroku 8. W przeciwnym razie kliknij Create New Virtual Device (Utwórz nowe urządzenie wirtualne).
  4. Na ekranie Wybierz sprzęt wybierz telefon, na przykład Pixel 2, i kliknij Dalej.
  5. Na ekranie Obraz systemu wybierz najnowszą wersję Androida, najlepiej z najwyższym poziomem interfejsu API. Jeśli nie jest zainstalowana, kliknij widoczny link Pobierz i pobierz aplikację.
  6. Kliknij Dalej.
  7. Na ekranie Urządzenie wirtualne z Androidem (AVD) pozostaw ustawienia bez zmian i kliknij Zakończ.
  8. W oknie docelowym wdrożenia wybierz urządzenie z Androidem.
  9. Kliknij OK.
  10. Android Studio kompiluje aplikację, wdraża ją i automatycznie otwiera na urządzeniu docelowym.

Gotowe! Powinna wyświetlić się strona logowania do Shrine z ćwiczenia z programowania MDC-101.

4cb0c218948144b4.png

Teraz gdy ekran logowania wygląda dobrze, dodajmy do aplikacji kilka produktów.

3. Dodawanie paska aplikacji u góry

Po zamknięciu strony logowania pojawia się ekran główny z komunikatem „Udało Ci się!”. Wspaniale. Jednak teraz użytkownik nie może podjąć żadnych działań ani nie zorientować się, gdzie się znajduje w aplikacji. Aby ułatwić sobie zadanie, dodajmy nawigację.

Material Design oferuje wzorce nawigacji, które zapewniają wysoką użyteczność. Jednym z najbardziej charakterystycznych elementów nawigacji jest górny pasek aplikacji.

Aby zapewnić nawigację i szybki dostęp do innych działań, dodajmy pasek aplikacji u góry.

Dodawanie widżetu paska aplikacji

W usłudze shr_product_grid_fragment.xml usuń tag <LinearLayout> zawierający wiadomość „Udało Ci się!” TextView i zastąp go następującym:

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>

Plik shr_product_grid_fragment.xml powinien wyglądać tak:

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>

Wiele pasków aplikacji ma przycisk obok tytułu. Dodajmy do naszego menu ikonę.

Dodawanie ikony nawigacji

W poziomie shr_product_grid_fragment.xml dodaj do komponentu XML Toolbar (który został właśnie dodany do układu) te elementy:

shr_product_grid_fragment.xml

app:navigationIcon="@drawable/shr_menu"

Plik shr_product_grid_fragment.xml powinien wyglądać tak:

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>

Dodaj przyciski poleceń i określ styl górnego paska aplikacji

Możesz też dodać przyciski po prawej stronie paska aplikacji. Na Androidzie są one nazywane przyciskami polecenia.

Automatycznie dodamy styl do górnego paska aplikacji i dodamy do jego menu przyciski poleceń.

Najpierw utwórzmy metodę konfigurowania paska narzędzi. Metoda powinna uzyskać odwołanie do paska narzędzi za pomocą parametru id, a także uzyskać odniesienie do aktywności za pomocą parametru getActivity(). Jeśli aktywność nie ma wartości null, ustaw Toolbar jako ActionBar za pomocą setSupportActionBar:

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

Następnie, bezpośrednio pod dodaną właśnie metodą setUpToolbar, zastąpmy onCreateOptionsMenu, aby rozszerzyć zawartość elementu shr_toolbar_menu.xml na pasku narzędzi:

ProductGridFragment.java

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

Teraz dodaj wywołanie do metody setUpToolbar, która została dodana do treści metody onCreateView(), za pomocą tego kodu:

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

Na koniec dodaj metodę onCreate() do ProductGridFragment.java. W treści metody ustaw parametr setHasOptionMenu jako true.

Powinna ona wyglądać tak:

ProductGridFragment.java

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

Powyższy kod ustawia pasek aplikacji z układu XML jako pasek czynności dla tej aktywności. Wywołanie onCreateOptionsMenu informuje aktywność, czego użyć jako menu. W takim przypadku na pasku aplikacji zostaną umieszczone pozycje menu z R.menu.shr_toolbar_menu.

Plik menu zawiera 2 elementy: „Szukaj” i „Filtr”.

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>

Po wprowadzeniu tych zmian plik ProductGridFragment.java powinien wyglądać tak:

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

}

Twórz i uruchamiaj. Twój ekran główny powinien wyglądać tak:

d04e8aa3b27f4754.png

Na pasku narzędzi po prawej stronie znajduje się teraz ikona nawigacji, tytuł i 2 ikony działań. Pasek narzędzi wyświetla też wzniesienie za pomocą subtelnego cienia, który wskazuje, że znajduje się ono na innej warstwie niż zawartość.

4. Dodaj kartę

Aplikacja ma już strukturę, więc uporządkujmy treści, umieszczając je na kartach.

Dodaj kartę

Zacznijmy od dodania karty pod górnym paskiem aplikacji. Karta powinna zawierać obszar na obraz, tytuł i etykietę dodatkowego tekstu.

W shr_product_grid_fragment.xml dodaj pod AppBarLayout:

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>

Kompilacja i uruchamianie:

f6184a55ccb5f920.png

Na tej podglądzie widać, że karta jest wsunięte od lewej krawędzi ekranu, ma zaokrąglone rogi i cień (który wyraża jej wysokość). Cały obszar nazywa się „kontenerem”. Oprócz samego kontenera wszystkie elementy w nim są opcjonalne.

Do kontenera możesz dodać te elementy: tekst nagłówka, miniaturę lub awatar, tekst podtytułu, podziały, a nawet przyciski i ikony. Na przykład utworzona przez nas karta zawiera dwa pola TextView (jeden dla tytułu, a drugi dla tekstu dodatkowego) w dokumencie LinearLayout, wyrównanym do dołu karty.

Karty są zwykle wyświetlane w kolekcji z innymi kartami. W następnej sekcji tego Codelab umieścimy je w ramach kolekcji w siatce.

5. Utwórz siatkę kart

Jeśli na ekranie znajduje się wiele kart, są one zgrupowane w jedną lub więcej kolekcji. Karty w siatce są w tej samej płaszczyźnie, co oznacza, że znajdują się na tej samej wysokości spoczynkowej co karty (chyba że zostaną wyciągnięte lub przeciągnięte, ale nie będziemy tego omawiać w tym ćwiczeniu).

Konfigurowanie siatki kart

Zapoznaj się z plikiem shr_product_card.xml, który Ci udostępniliśmy:

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>

Ten układ karty zawiera kartę z obrazem (tutaj NetworkImageView, która umożliwia nam uwzględnienie obrazów z adresu URL) oraz 2 elementy TextViews.

Następnie sprawdź ProductCardRecyclerViewAdapter, które dla Ciebie przygotowaliśmy. Jest w tym samym pakiecie co 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();
   }
}

Klasa adaptera zarządza zawartością siatki. Aby określić, co ma się stać z danymi treściami w przypadku poszczególnych widoków, wkrótce napiszemy kod dla onBindViewHolder().

W tym samym pakiecie możesz też przyjrzeć się ProductCardViewHolder. Ta klasa przechowuje widoki, które wpływają na układ karty, dzięki czemu możemy je później modyfikować.

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

Aby skonfigurować siatkę, najpierw musimy usunąć obiekt zastępczy MaterialCardView z elementu shr_product_grid_fragment.xml. Następnie dodaj komponent reprezentujący naszą siatkę kart. W takim przypadku dodaj komponent RecyclerView do elementu shr_product_grid_fragment.xml pod komponentem XML AppBarLayout:

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>

shr_product_grid_fragment.xml powinien wyglądać tak:

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>

Na koniec w pliku onCreateView() dodaj kod inicjowania RecyclerView do funkcji ProductGridFragment.java po wywołaniu funkcji setUpToolbar(view) i przed instrukcją return:

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

Powyższy fragment kodu zawiera kroki inicjowania niezbędne do skonfigurowania RecyclerView. Obejmuje to wybór menedżera układu RecyclerView oraz zainicjowanie i ustawienie adaptera RecyclerView.

Twój plik ProductGridFragment.java powinien teraz wyglądać tak:

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

}

Twórz i uruchamiaj.

f9aeab846fc3bb4c.png

Karty już są! Na razie nie wyświetlają one niczego, więc dodajmy dane produktów.

Dodawanie obrazów i tekstu

Do każdej karty dodaj zdjęcie, nazwę produktu i cenę. Nasz abstrakcja ViewHolder obejmuje wyświetlenia każdej karty. W ViewHolder dodaj te 3 widoki w następujący sposób:

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

W adapterze RecyclerView w narzędziu ViewHolder, zaktualizuj metodę onBindViewHolder(), aby ustawić informacje w każdym widoku:

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

Powyższy kod informuje adapter naszego RecyclerView, co zrobić z każdą kartą przy użyciu ViewHolder.

Tutaj ustawia dane tekstowe w każdym z elementów ViewHolder oraz wywołuje funkcję ImageRequester, aby pobrać obraz z adresu URL. ImageRequester to zajęcia, które udostępniliśmy dla wygody użytkowników i korzystają z biblioteki Volley (temat wykracza poza zakres tego ćwiczenia w programowaniu, ale możesz samodzielnie zapoznać się z kodem).

Kompilacja i uruchamianie:

249db074eff043f4.png

Nasze produkty są teraz widoczne w aplikacji.

6. Podsumowanie

Nasza aplikacja ma podstawowy proces, który prowadzi użytkownika od ekranu logowania do ekranu głównego, na którym można przeglądać produkty. Za pomocą kilku linii kodu dodaliśmy pasek aplikacji z nazwą i 3 przyciskami oraz siatkę kart, aby zaprezentować zawartość aplikacji. Ekran główny jest teraz prosty i funkcjonalny, a jego podstawowa struktura zawiera treści, które można wykorzystać.

Dalsze kroki

Użyliśmy 4 głównych komponentów Material Design z biblioteki MDC-Android na górnym pasku aplikacji, karcie, polu tekstowym i przycisku. Więcej komponentów znajdziesz w katalogu MDC-Android Komponenty w MDC Android.

Jest w pełni funkcjonalna, ale nie promuje jeszcze żadnej marki. W sekcji MDC-103: Motywowanie interfejsu Material Design za pomocą koloru, kształtu, wyeksponowania i typu dostosujemy styl tych komponentów, aby odzwierciedlał żywą, nowoczesną markę.

Udało mi się ukończyć to ćwiczenia z programowania w rozsądny sposób i w rozsądny sposób

Zdecydowanie się zgadzam Zgadzam się Nie mam zdania Nie zgadzam się Zdecydowanie się nie zgadzam

Chcę w przyszłości nadal używać komponentów Material Komponenty

Zdecydowanie się zgadzam Zgadzam się Nie mam zdania Nie zgadzam się Zdecydowanie się nie zgadzam