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 kursie MDC-101 do utworzenia strony logowania użyto 2 komponentów Material Design: pól tekstowych i przycisków z efektem rozchodzenia się fali. 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 masz już za sobą MDC-101, Twój kod powinien być gotowy do tego ćwiczenia. Przejdź 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/kotlin
. 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 kotlin –> shrine(lub wyszukaj na komputerze shrine), aby otworzyć projekt Shipping.
- 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.gradle
modułuapp
i upewnij się, że blokdependencies
zawiera 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 najbardziej widocznych elementów 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ń blok <LinearLayout>
zawierający tekst „Udało Ci 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 teraz 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 shr_product_grid_fragment.xml
dodaj do komponentu Toolbar
XML, 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 działań.
W funkcji ProductGridFragment.kt
onCreateView
ustaw activity
Toolbar
, które mają być używane jako ActionBar
, za pomocą setSupportActionBar
. Możesz to zrobić po utworzeniu widoku za pomocą ikony inflater
.
ProductGridFragment.kt
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment with the ProductGrid theme
val view = inflater.inflate(R.layout.shr_product_grid_fragment, container, false)
// Set up the toolbar.
(activity as AppCompatActivity).setSupportActionBar(view.app_bar)
return view;
}
Następnie bezpośrednio pod metodą, którą właśnie zmieniliśmy, aby skonfigurować pasek narzędzi, zastąpmy onCreateOptionsMenu
, aby wstawić zawartość shr_toolbar_menu.xml
na pasek narzędzi:
ProductGridFragment.kt
override fun onCreateOptionsMenu(menu: Menu, menuInflater: MenuInflater) {
menuInflater.inflate(R.menu.shr_toolbar_menu, menu)
super.onCreateOptionsMenu(menu, menuInflater)
}
Na koniec zastąp onCreate()
w ProductGridFragment.kt
, a po wywołaniu super()
wywołaj setHasOptionMenu
z true
:
ProductGridFragment.kt
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
}
Powyższe fragmenty kodu ustawiają 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.kt
powinien wyglądać tak:
ProductGridFragment.kt
package com.google.codelabs.mdc.kotlin.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 androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.GridLayoutManager
import com.google.codelabs.mdc.kotlin.shrine.network.ProductEntry
import kotlinx.android.synthetic.main.shr_product_grid_fragment.view.*
class ProductGridFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment with the ProductGrid theme
val view = inflater.inflate(R.layout.shr_product_grid_fragment, container, false)
// Set up the tool bar
(activity as AppCompatActivity).setSupportActionBar(view.app_bar)
return view;
}
override fun 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 wyświetla też wysokość za pomocą subtelnego cienia, który pokazuje, ż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. Dodaj te informacje w sekcji shr_product_grid_fragment.xml
pod sekcją 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>
Kompilowanie i uruchamianie:
W tym podglądzie widać, że karta jest odsunięta od lewej krawędzi, ma zaokrąglone rogi i cień (który wskazuje wysokość karty). Cały element nazywa się „kontenerem”. Oprócz 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 jest to NetworkImageView
, który umożliwia wczytywanie i wyświetlanie obrazów z adresu URL) oraz 2 elementy TextViews
.
Następnie przyjrzyj się ProductCardRecyclerViewAdapter
, które dla Ciebie przygotowaliśmy. Jest w tym samym pakiecie co ProductGridFragment
.
ProductCardRecyclerViewAdapter.kt
package com.google.codelabs.mdc.kotlin.shrine
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.google.codelabs.mdc.kotlin.shrine.network.ProductEntry
/**
* Adapter used to show a simple grid of products.
*/
class ProductCardRecyclerViewAdapter(private val productList: List<ProductEntry>) : RecyclerView.Adapter<ProductCardViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProductCardViewHolder {
val layoutView = LayoutInflater.from(parent.context).inflate(R.layout.shr_product_card, parent, false)
return ProductCardViewHolder(layoutView)
}
override fun onBindViewHolder(holder: ProductCardViewHolder, position: Int) {
// TODO: Put ViewHolder binding code here in MDC-102
}
override fun getItemCount(): Int {
return productList.size
}
}
Klasa adaptera powyżej zarządza zawartością naszej siatki. Aby określić, co ma robić każdy widok z danymi treściami, 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ć.
package com.google.codelabs.mdc.kotlin.shrine
import android.view.View
import androidx.recyclerview.widget.RecyclerView
class ProductCardViewHolder(itemView: View) //TODO: Find and store views from itemView
: RecyclerView.ViewHolder(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 użyjemy elementu RecyclerView. 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.kt
po wywołaniu setUpToolbar(view)
i przed instrukcją return
:
ProductGridFragment.kt
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment with the ProductGrid theme
val view = inflater.inflate(R.layout.shr_product_grid_fragment, container, false)
// Set up the toolbar.
(activity as AppCompatActivity).setSupportActionBar(view.app_bar)
// Set up the RecyclerView
view.recycler_view.setHasFixedSize(true)
view.recycler_view.layoutManager = GridLayoutManager(context, 2, RecyclerView.VERTICAL, false)
val adapter = ProductCardRecyclerViewAdapter(
ProductEntry.initProductEntryList(resources))
view.recycler_view.adapter = adapter
val largePadding = resources.getDimensionPixelSize(R.dimen.shr_product_grid_spacing)
val smallPadding = resources.getDimensionPixelSize(R.dimen.shr_product_grid_spacing_small)
view.recycler_view.addItemDecoration(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.kt
powinien teraz wyglądać tak:
ProductGridFragment.kt
package com.google.codelabs.mdc.kotlin.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 androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.codelabs.mdc.kotlin.shrine.network.ProductEntry
import kotlinx.android.synthetic.main.shr_product_grid_fragment.view.*
class ProductGridFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment with the ProductGrid theme
val view = inflater.inflate(R.layout.shr_product_grid_fragment, container, false)
// Set up the toolbar.
(activity as AppCompatActivity).setSupportActionBar(view.app_bar)
// Set up the RecyclerView
view.recycler_view.setHasFixedSize(true)
view.recycler_view.layoutManager = GridLayoutManager(context, 2, RecyclerView.VERTICAL, false)
val adapter = ProductCardRecyclerViewAdapter(
ProductEntry.initProductEntryList(resources))
view.recycler_view.adapter = adapter
val largePadding = resources.getDimensionPixelSize(R.dimen.shr_product_grid_spacing)
val smallPadding = resources.getDimensionPixelSize(R.dimen.shr_product_grid_spacing_small)
view.recycler_view.addItemDecoration(ProductGridItemDecoration(largePadding, smallPadding))
return view;
}
override fun onCreateOptionsMenu(menu: Menu, menuInflater: MenuInflater) {
menuInflater.inflate(R.menu.shr_toolbar_menu, menu)
super.onCreateOptionsMenu(menu, menuInflater)
}
}
Kompilowanie i uruchamianie:
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.kt
package com.google.codelabs.mdc.kotlin.shrine
import android.view.View
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.android.volley.toolbox.NetworkImageView
class ProductCardViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var productImage: NetworkImageView = itemView.findViewById(R.id.product_image)
var productTitle: TextView = itemView.findViewById(R.id.product_title)
var productPrice: TextView = itemView.findViewById(R.id.product_price)
}
Zaktualizuj metodę onBindViewHolder()
w ProductCardRecyclerViewAdapter
, aby ustawić tytuł, cenę i zdjęcie produktu dla każdego widoku produktu, jak pokazano poniżej:
ProductCardRecyclerViewAdapter.kt
override fun onBindViewHolder(holder: ProductCardViewHolder, position: Int) {
if (position < productList.size) {
val product = productList[position]
holder.productTitle.text = product.title
holder.productPrice.text = 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 ViewHolder
TextView
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.
Aplikacja jest w pełni funkcjonalna, ale nie ma jeszcze określonej marki ani stylu. W module MDC-103: Material Design Theming with Color, Shape, Elevation and Type dostosujemy styl tych komponentów, aby odzwierciedlały żywą, nowoczesną markę.