Komponenty Material (MDC) pomagają deweloperom wdrażać Material Design. MDC to stworzona przez zespół inżynierów i projektantów UX z Google biblioteka zawierająca dziesiątki atrakcyjnych i funkcjonalnych komponentów interfejsu. Jest dostępna na platformy Android, iOS, internet i Flutter. material.io/develop |
W samouczku MDC-101 do utworzenia strony logowania użyto 2 komponentów Material Design (MDC): pól tekstowych i przycisków. Teraz rozbudujmy tę podstawę, dodając nawigację, strukturę i dane.
Co utworzysz
W tym laboratorium kodowania utworzysz ekran główny aplikacji Shrine, czyli aplikacji do handlu elektronicznego, w której sprzedawane są ubrania i artykuły gospodarstwa domowego. Będzie ona zawierać:
- Górny pasek aplikacji
- Lista produktów w formie siatki

Komponenty MDC-Android w tym kursie
- AppBarLayout
- MaterialCardView
Czego potrzebujesz
- Podstawowa wiedza na temat programowania aplikacji na Androida
- Android Studio (jeśli nie masz jeszcze tego środowiska, pobierz je tutaj)
- emulator lub urządzenie z Androidem (dostępne w Android Studio);
- Przykładowy kod (patrz następny krok)
Jak oceniasz swoje doświadczenie w tworzeniu aplikacji na Androida?
Kontynuujesz naukę z MDC-101?
Jeśli udało Ci się ukończyć MDC-101, Twój kod powinien być gotowy do tego ćwiczenia. Możesz przejść do kroku 3: Dodaj górny pasek aplikacji.
Zaczynasz od zera?
Pobieranie aplikacji do ćwiczeń z programowania
Aplikacja startowa znajduje się w katalogu material-components-android-codelabs-102-starter/java. Zanim zaczniesz, cd do tego katalogu.
...lub sklonuj go z GitHub
Aby sklonować ten codelab 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
- Gdy kreator konfiguracji zakończy działanie i wyświetli 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 –> shrine(lub wyszukaj na komputerze shrine), aby otworzyć projekt Shrine.
- Poczekaj chwilę, aż Android Studio utworzy i zsynchronizuje projekt. Wskaźniki aktywności w dolnej części okna Android Studio będą pokazywać postęp.
- W tym momencie Android Studio może zgłosić błędy kompilacji, ponieważ brakuje Ci pakietu SDK Androida lub narzędzi do kompilacji, np. takich jak te pokazane poniżej. Postępuj zgodnie z instrukcjami w Android Studio, aby zainstalować lub zaktualizować te komponenty i zsynchronizować projekt.
Dodawanie zależności projektu
Projekt musi być zależny od biblioteki pomocy MDC na Androida. Pobrany przykładowy kod powinien już zawierać tę zależność, ale warto wykonać poniższe czynności, aby się upewnić.
- Otwórz plik
build.gradlemodułuappi upewnij się, że blokdependencieszawiera zależność od MDC Android:
api 'com.google.android.material:material:1.1.0-alpha06'
- (Opcjonalnie) W razie potrzeby edytuj plik
build.gradle, aby dodać te zależności, i zsynchronizuj 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'
}Uruchom aplikację startową
|
Gotowe! Powinna wyświetlić się strona logowania Shrine z ćwiczenia MDC-101.

Ekran logowania wygląda już dobrze, więc teraz wypełnimy aplikację produktami.
Po zamknięciu strony logowania wyświetli się ekran główny z komunikatem „Udało Ci się!”. Wspaniale. Ale teraz użytkownik nie może podjąć żadnych działań ani nie wie, gdzie znajduje się w aplikacji. Aby mu w tym pomóc, dodajmy nawigację.
Material Design oferuje wzorce nawigacji, które zapewniają wysoki poziom użyteczności. Jednym z najważniejszych elementów nawigacji jest górny pasek aplikacji.
Aby zapewnić nawigację i umożliwić użytkownikom szybki dostęp do innych działań, dodajmy górny pasek aplikacji.
Dodawanie widżetu AppBar
W shr_product_grid_fragment.xml usuń tag <LinearLayout> zawierający tekst „Udało się!”. TextView i zastąp go tym tekstem:
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 niego ikonę menu.
Dodawanie ikony nawigacji
W aplikacji 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>Dodawanie przycisków działań i stylizowanie górnego paska aplikacji
Możesz też dodać przyciski po prawej stronie paska aplikacji. Na urządzeniach z Androidem są one nazywane przyciskami działania.
Programowo nadamy styl górnemu paskowi aplikacji i dodamy do jego menu przyciski poleceń.
Najpierw utwórzmy metodę konfigurowania paska narzędzi. Metoda powinna pobrać odwołanie do paska narzędzi za pomocą id, a także odwołanie do aktywności za pomocą getActivity(). Jeśli aktywność nie jest wartością null, ustaw Toolbar, aby używać go 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ą metodą setUpToolbar zastąpmy metodę onCreateOptionsMenu, aby umieścić zawartość 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 metody setUpToolbar, którą dodaliśmy do treści metody onCreateView(), w ten sposób:
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 onCreate() do ProductGridFragment.java. W treści metody ustaw parametr setHasOptionMenu jako true.
Metoda powinna wyglądać tak:
ProductGridFragment.java
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}Powyższy kod ustawia pasek aplikacji z naszego układu XML jako pasek działań dla tej aktywności. Wywołanie zwrotne onCreateOptionsMenu informuje aktywność, co ma być używane jako menu. W tym przypadku umieści on elementy menu z R.menu.shr_toolbar_menu na pasku aplikacji.
Plik menu zawiera 2 elementy: „Szukaj” i „Filtruj”.
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);
}
}Skompiluj i uruchom. Ekran główny powinien wyglądać tak:

Teraz pasek narzędzi zawiera ikonę nawigacji, tytuł i 2 ikony działań po prawej stronie. Pasek narzędzi jest też wyświetlany z niewielkim cieniem, który wskazuje, że znajduje się on na innej warstwie niż treść.
Aplikacja ma już pewną strukturę, więc uporządkujmy treści, umieszczając je na kartach.
Dodawanie karty
Zacznijmy od dodania jednej karty pod górnym paskiem aplikacji. Karta powinna zawierać obszar na obraz, tytuł i etykietę tekstu dodatkowego.
W pliku shr_product_grid_fragment.xml dodaj pod elementem AppBarLayout ten kod:
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>Kompilowanie i uruchamianie:

W tym podglądzie widać, że karta jest odsunięta od lewej krawędzi ekranu, ma zaokrąglone rogi i cień (który wskazuje wysokość karty). 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, separatory, a nawet przyciski i ikony. Na przykład utworzona przez nas karta zawiera 2 elementy TextView (jeden dla tytułu, a drugi dla tekstu dodatkowego) w elemencie LinearLayout, wyrównane do dołu karty.
Karty są zwykle wyświetlane w kolekcji z innymi kartami. W następnej sekcji tego laboratorium pokażemy, jak wyświetlić je w siatce.
Gdy na ekranie znajduje się kilka kart, są one zgrupowane w 1 lub więcej kolekcji. Karty w siatce są współpłaszczyznowe, co oznacza, że znajdują się na tej samej wysokości (chyba że zostaną podniesione lub przeciągnięte, ale nie będziemy tego omawiać w tym laboratorium).
Konfigurowanie siatki kart
Sprawdź shr_product_card.xml plik, który dla Ciebie przygotowaliś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 (w tym przypadku NetworkImageView, co pozwala nam umieszczać obrazy z adresu URL) i 2 elementy TextViews.
Następnie przyjrzyj się 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 powyżej zarządza zawartością naszej siatki. Aby określić, co ma robić każdy widok z daną treścią, wkrótce napiszemy kod dla onBindViewHolder().
W tym samym pakiecie możesz też sprawdzić 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 usuń symbol zastępczy MaterialCardView z shr_product_grid_fragment.xml. Następnie dodaj komponent reprezentujący siatkę kart. W tym przypadku dodaj komponent RecyclerView do elementu shr_product_grid_fragment.xml poniżej komponentu 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>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>
<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 pliku ProductGridFragment.java po wywołaniu 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 niezbędne kroki inicjowania, które pozwalają skonfigurować RecyclerView. Obejmuje to ustawienie menedżera układu RecyclerView oraz zainicjowanie i ustawienie adaptera RecyclerView.
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);
}
}Skompiluj i uruchom.
Karty są już dostępne. Nie wyświetlają one jeszcze żadnych informacji, więc dodajmy dane o produktach.
Dodawanie obrazów i tekstu
Do każdej karty dodaj obraz, nazwę produktu i cenę. Nasza ViewHolder abstrakcja zawiera widoki poszczególnych kart. W naszym ViewHolder dodaj 3 widoki w ten 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 funkcji 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 RecyclerView o tym, co ma zrobić z każdą kartą, za pomocą ViewHolder.
W tym przypadku ustawia dane tekstowe w każdym z elementów ViewHolderTextView i wywołuje funkcję ImageRequester, aby pobrać obraz z adresu URL. ImageRequester to klasa, którą udostępniliśmy dla Twojej wygody. Korzysta ona z biblioteki Volley (to temat wykraczający poza zakres tych warsztatów, ale możesz samodzielnie zapoznać się z kodem).
Kompilowanie i uruchamianie:

Nasze produkty wyświetlają się teraz w aplikacji.
Nasza aplikacja ma podstawowy proces, który prowadzi użytkownika od ekranu logowania do ekranu głównego, na którym można wyświetlać produkty. W kilku wierszach kodu dodaliśmy górny pasek aplikacji z tytułem i 3 przyciskami oraz siatkę kart do prezentowania treści aplikacji. Ekran główny jest teraz prosty i funkcjonalny, ma podstawową strukturę i zawiera treści, które można wykorzystać.
Dalsze kroki
Użyliśmy już 4 podstawowych komponentów Material Design z biblioteki MDC-Android: górnego paska aplikacji, karty, pola tekstowego i przycisku. Więcej komponentów znajdziesz w katalogu MDC-Android komponentów w MDC Android.
Aplikacja jest w pełni funkcjonalna, ale nie promuje jeszcze żadnej konkretnej marki. W module MDC-103: Material Design Theming with Color, Shape, Elevation and Type dostosujemy styl tych komponentów, aby odzwierciedlały żywą, nowoczesną markę.
