Cvičenie 4 - Dizajn, RecyclerView
Úlohy pre 4. cvičenie
- 1. Vylepšenie dizajnu aplikácie.
- 2. Použitie prekladov v aplikácii.
- 3. Vytvorenie skrolovateľného zoznamu položiek pomocou RecyclerView.
Hodnotenie
Prve hodnotenie aplikacii bude na 5. cviceni, kde treba mat hotove vsetky ulohy pre moznost ziskania max. poctu bodov.
1. Vylepšenie dizajnu aplikácie.
Krok 1: Pochopte hierarchiu štýlov
Androidová hierarchia štýlov je organizovaná tak, aby umožňovala konzistentnosť dizajnu a zároveň flexibilitu pre jednotlivé komponenty. Táto hierarchia má tri hlavné časti:
- Zobrazené atribúty (View Attributes): Sú to vlastnosti, ktoré môžete nastaviť priamo na jednotlivé komponenty (views) vo vašom XML layoute. Sú to najkonkrétnejšie nastavenia, ktoré majú najvyššiu prioritu.
- Štýly (Styles): Štýly sú zoskupenia zobrazených atribútov. Môžete si predstaviť štýl ako "predlohu" alebo "súbor" nastavení, ktoré sa môžu opakovane použiť na rôzne komponenty v layoute.
- Témy (Themes): Sú to kolekcie štýlov a zobrazených atribútov, ktoré sa aplikujú na celú aplikáciu alebo časti aplikácie. Témy nastavujú všeobecný vzhľad a pocit aplikácie.
Je dôležité si uvedomiť: Ak sa rovnaký atribút definuje vo View, v štýle a v téme, atribút z View má najvyššiu prioritu (tzn. prekryje ostatné), štýl má strednú prioritu a téma má najnižšiu prioritu. Inými slovami, Zobrazené atribúty prepíšu Štýly, a Štýly prepíšu Témy.
Krok 2: Používanie zobrazených atribútov
Každý komponent (view) vo vašom layoute môže mať atribúty. Tieto atribúty môžu byť špecifikované priamo v XML súbore layoutu.
Napríklad, ak chcete, aby váš TextView mal červený text veľkosti 18sp, môžete nastaviť tieto atribúty priamo:
<TextView android:text="Ahoj svet!" android:textColor="#FF0000" android:textSize="18sp" ... />
Ak nastavíte štýl alebo tému s inými hodnotami pre tieto atribúty, tieto hodnoty z TextView budú mať prednosť.
Krok 3: Vytvorenie a použitie štýlu
Štýly umožňujú znovu použiť skupinu atribútov naprieč rôznymi komponentami. Znížite tak redundanciu a zjednodušíte úpravy dizajnu.
Vytvorte štýl v súbore res/values/styles.xml
:
<style name="TextStyle"> <item name="android:textColor">#FF0000</item> <item name="android:textSize">18sp</item> </style>
Použite štýl v komponente:
<TextView android:text="Ahoj svet!" style="@style/TextStyle" ... />
Krok 4: Vytvorenie a použitie témy
Témy definujú celkový vzhľad vašej aplikácie. Aplikujú sa buď na celú aplikáciu alebo len na časti aplikácie.
Vytvorenie témy v res/values/styles.xml
:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <item name="colorPrimary">#3F51B5</item> <item name="colorPrimaryDark">#303F9F</item> <item name="colorAccent">#FF4081</item> </style>
Aplikácia témy pre aplikáciu v AndroidManifest.xml
:
<application android:theme="@style/AppTheme" ... />
Krok 5: Dedičnosť štýlov a prepisovanie
Predstavte si, že máte základný štýl textu, ktorý chcete použiť na viacerých miestach vo vašej aplikácii, ale s niekoľkými malými zmenami v niektorých prípadoch.
Vytvoríme základný štýl textu v res/values/styles.xml
:
<style name="BaseTextStyle"> <item name="android:textSize">16sp</item> <item name="android:textColor">#000000</item> </style>
Ak chcete vytvoriť variáciu tohto štýlu s väčšou veľkosťou textu, môžete vytvoriť nový štýl, ktorý dedí z "BaseTextStyle" a prepíše požadovaný atribút:
<style name="LargeTextStyle" parent="BaseTextStyle"> <item name="android:textSize">24sp</item> </style>
Keď použijete štýl LargeTextStyle
na TextView v XML layoute, tento TextView bude mať čiernu farbu textu (zdedenú z BaseTextStyle) a veľkosť 24sp (prepisuje základný štýl).
Krok 6: Implementácia nočného režimu
Nočný režim umožňuje zmeniť vzhľad aplikácie podľa denného času alebo nastavení zariadenia. Aby ste podporili nočný režim, môžete definovať špecifické štýly a témy pre tento režim.
Vytvorenie štýlu pre nočný režim v res/values-night/styles.xml
:
<style name="TextStyleNight"> <item name="android:textColor">#FFFFFF</item> <item name="android:textSize">18sp</item> </style>
Pri aktivovanom nočnom režime sa automaticky použije tento štýl, ak je nastavený na komponente.
Krok 7: Pochopte a použite dp a sp
dp (Density-independent Pixels): Je to jednotka, ktorá sa používa na určenie rozmieru komponentu nezávisle od hustoty obrazovky. Umožňuje konzistentný vzhľad naprieč rôznymi zariadeniami.
sp (Scale-independent Pixels): Je to jednotka používaná pre text. Podobne ako dp, ale berie do úvahy aj nastavenia veľkosti textu užívateľa.
Je dôležité používať tieto jednotky pre dosiahnutie konzistentného a prispôsobivého dizajnu naprieč rôznymi zariadeniami.
Krok 8: Používanie Material Design
Material Design je dizajnový jazyk vyvinutý Google. Poskytuje sadu komponentov, štýlov a usmernení pre vývoj kvalitných Android aplikácií. Ak chcete začať používať Material Design, pridajte závislosť v `build.gradle`:
implementation(libs.material)
Použitie Material Button
<com.google.android.material.button.MaterialButton
android:id="@+id/materialButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Stlač ma!"
app:cornerRadius="8dp" />
Kotlin:
val button = findViewById<MaterialButton>(R.id.materialButton)
button.setOnClickListener {
// kód po stlačení tlačidla
}

Použitie Material Floating Action Button (FAB)
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/description"
app:srcCompat="@drawable/ic_add_white_24dp" />
Kotlin:
val fab = findViewById<FloatingActionButton>(R.id.fab)
fab.setOnClickListener {
// kód po stlačení FAB
}

Použitie Material TextInputLayout
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Zadajte text">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</com.google.android.material.textfield.TextInputLayout>

Krok 6: Použitie Material Snackbar
val view = findViewById<View>(R.id.container)
Snackbar.make(view, "Toto je Snackbar", Snackbar.LENGTH_LONG)
.setAction("Akcia") {
// kód po stlačení akcie na Snackbar
}.show()

3. Použitie prekladov v aplikácii.
Krok 1: Vytvorenie predvolených reťazcových zdrojov
Vaše predvolené reťazce by mali byť definované v res/values/strings.xml
. Napríklad:
<resources> <string name="app_name">Moja Aplikácia</string> <string name="welcome_message">Vitajte v mojej aplikácii!</string> </resources>
Krok 2: Pridanie prekladov
Ak chcete pridať preklady, vytvorte ďalšie priečinky zdrojových hodnôt pre každý jazyk, ktorý chcete podporovať. Napríklad pre francúzštinu vytvorte priečinok res/values-fr
a pre Nemčinu res/values-de
.
Pre francúzštinu, res/values-fr/strings.xml
môže vyzerať nasledovne:
<resources> <string name="app_name">Mon Application</string> <string name="welcome_message">Bienvenue dans mon application!</string> </resources>
Krok 3: Použitie preložených reťazcov v kóde a XML
Pri použití reťazcov v kóde alebo XML, odkazujte sa na nich normálne pomocou @string/app_name
. Android automaticky vyberie správny preklad na základe nastavenia jazyka zariadenia.
Krok 4: Testovanie prekladov
Aby ste otestovali rôzne preklady, zmeňte jazyk vášho Android zariadenia alebo emulátora. Uistite sa, že vaša aplikácia správne zobrazuje preložené reťazce.
Ak máte zariadenie s viacerými jazykmi, Android by mal automaticky zvoliť najvhodnejší preklad z dostupných prekladov vo vašej aplikácii.
Krok 5: Udržujte preklady aktuálne
Ak pridáte alebo zmeníte reťazce v predvolenej verzii, uistite sa, že aktualizujete aj všetky preklady. Existujú nástroje a služby, ktoré vám môžu pomôcť synchronizovať a spravovať preklady pre Android aplikácie.
3. Vytvorenie skrolovateľného zoznamu položiek pomocou RecyclerView
Krok 1: Vytvorenie XML layout pre RecyclerView
Tento XML kód je určený pre layout v Android aplikácii a obsahuje dva hlavné komponenty: BottomBar
a RecyclerView
.
RecyclerView
je flexibilná komponenta zobrazenia, ktorá je optimalizovaná pre veľké súbory dát, ktoré sa menia v čase. Tento konkrétny RecyclerView
je nastavený tak, aby vyplnil všetok dostupný priestor medzi vrchom rodičovského view a spodnou časťou BottomBar
.
fragment_example.xml
:
<eu.mcomputing.mobv.mobvzadanie.BottomBar android:id="@+id/bottom_bar" android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" /> <androidx.recyclerview.widget.RecyclerView app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toTopOf="@id/bottom_bar" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" android:layout_height="0dp" android:layout_width="match_parent"/>
Šírka je nastavená na match_parent
, čo znamená, že RecyclerView
bude mať rovnakú šírku ako jeho rodičovský view. Výška je nastavená na 0dp
, čo v kombinácii s hornými a dolnými obmedzeniami zabezpečuje, že RecyclerView
sa rozťahuje, aby vyplnila dostupný vertikálny priestor.
Krok 2: Vytvorenie XML layout pre riadok v zozname
Tento XML kód definuje layout pre jednotlivé riadky zobrazené v rámci komponentu RecyclerView. Skladá sa z ConstraintLayout, ktorý obsahuje ImageView a TextView.
ConstraintLayout je použitý ako kontajner pre riadok, čo umožňuje flexibilné rozmiestnenie a veľkosť komponentov vo vnútri. Tento layout sa rozširuje na celú šírku rodičovského view a obaluje obsah pre výšku.
Okrem toho, margin definovaný v android:layout_margin
poskytuje odsadenie od okrajov rodičovského view.
ImageView
je použitý pre zobrazenie obrázka v riadku. Jeho šírka a výška sú nastavené na wrap_content
, čo znamená, že view si zmení svoje rozmery podľa veľkosti obrázka.
Použitie layout_constraint*
atribútov zabezpečuje, že tento view je ukotvený na vrch a začiatok rodičovského view v rámci ConstraintLayout.
TextView
je použitý pre zobrazenie textu v riadku. Jeho šírka a výška sú nastavené na wrap_content
, čo znamená, že view si zmení svoje rozmery podľa obsahu textu.
Text je posunutý od začiatku obrázka s definovaným odsadením a je ukotvený na vrch rodičovského view.
Vytvorte súborfeed_item.xml
:
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="@dimen/activity_horizontal_margin" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"> <ImageView android:id="@+id/item_image" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/item_text" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintStart_toEndOf="@id/item_image" app:layout_constraintTop_toTopOf="parent" android:layout_marginStart="@dimen/activity_horizontal_margin" /> </androidx.constraintlayout.widget.ConstraintLayout>
Krok 3: Implementácia adaptéra
RecyclerView.Adapter
je kľúčovou súčasťou práce s RecyclerView
v Android aplikáciách. Tento adaptér je zodpovedný za poskytovanie viewholderov, ktoré reprezentujú položky dát, a tiež za väzbu dát k týmto viewholderom keď sú tieto položky zobrazené na obrazovke.
Pred implementáciou adaptéra musíte najprv definovať ViewHolder
. Táto vnútorná trieda rozširuje RecyclerView.ViewHolder
a uchováva informácie o jednotlivých položkách zoznamu.
class CustomViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val imageView: ImageView = view.findViewById(R.id.item_image)
val textView: TextView = view.findViewById(R.id.item_text)
}
V tomto príklade, CustomViewHolder
obsahuje referencie na ImageView
a TextView
, ktoré sa používajú na zobrazenie dát pre jednu položku v RecyclerView
.
Adaptér potrebuje prepísať tri metódy: onCreateViewHolder()
, onBindViewHolder()
, a getItemCount()
.
class CustomAdapter(private val data: List<DataType>) : RecyclerView.Adapter<CustomViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_layout, parent, false)
return CustomViewHolder(view)
}
override fun onBindViewHolder(holder: CustomViewHolder, position: Int) {
val item = data[position]
// Bind data to ViewHolder
}
override fun getItemCount(): Int = data.size
}
V metóde onCreateViewHolder()
, adaptér inflates the layout pre každú položku a inicializuje ViewHolder. V metóde onBindViewHolder()
, adaptér priradí dáta (získané z vašej dátovej sady) k elementom view udržiavaným ViewHolder-om. Metóda getItemCount()
jednoducho vráti počet položiek v dátovej sade.
Nakoniec, po vytvorení adaptéra, musíte ho priradiť k inštancii RecyclerView
.
val recyclerView: RecyclerView = findViewById(R.id.my_recycler_view)
recyclerView.adapter = CustomAdapter(myDataList)
recyclerView.layoutManager = LinearLayoutManager(this)
Toto priradenie zabezpečuje, že RecyclerView
bude vedieť, ako vytvárať a napĺňať jednotlivé riadky na základe dát poskytnutých adaptérom.
Príklad adaptéra: FeedAdapter
Nižšie je príklad adaptéra pre RecyclerView s vlastným layoutom, ktorý obsahuje ImageView a TextView:
Vytvorte nový Kotlin súbor s názvom FeedAdapter.kt
a implementujte adaptér.
package eu.mcomputing.mobv.mobvzadanie import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.ImageView import android.widget.TextView import androidx.recyclerview.widget.RecyclerView data class MyItem(val imageResource: Int, val text: String) class FeedAdapter : RecyclerView.Adapter<FeedAdapter.FeedViewHolder>() { private var items: List<MyItem> = listOf() // ViewHolder poskytuje odkazy na zobrazenia v každej položke class FeedViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) // Táto metóda vytvára nový ViewHolder override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FeedViewHolder { val view = LayoutInflater.from(parent.context) .inflate(R.layout.feed_item, parent, false) return FeedViewHolder(view) } // Táto metóda prepojí dáta s ViewHolderom override fun onBindViewHolder(holder: FeedViewHolder, position: Int) { holder.itemView.findViewById<ImageView>(R.id.item_image).setImageResource(items[position].imageResource) holder.itemView.findViewById<TextView>(R.id.item_text).text = items[position].text } // Vracia počet položiek v zozname override fun getItemCount() = items.size fun updateItems(newItems: List<MyItem>) { items = newItems notifyDataSetChanged() } }
Tento kód demonštruje, ako vytvoriť adaptér pre RecyclerView
, ktorý obsahuje zoznam položiek typu MyItem
. Každá položka MyItem
má dva atribúty: imageResource
pre ukladanie referencie na obrázok a text
pre ukladanie textového reťazca.
data class MyItem(val imageResource: Int, val text: String): Definuje dátovú triedu v Kotlin, ktorá reprezentuje položku so dvoma vlastnosťami: obrázok a text.
class FeedAdapter : RecyclerView.Adapter<FeedAdapter.FeedViewHolder>(): Definuje adaptér dedičný od RecyclerView.Adapter
s vnorenou triedou FeedViewHolder
.
class FeedViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView): Táto vnorená trieda rozširuje RecyclerView.ViewHolder
a poskytuje referencie na zobrazenia pre každú položku v RecyclerView
.
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FeedViewHolder: Táto metóda inflates (načíta) layout pre každú položku v RecyclerView
a inicializuje FeedViewHolder
.
override fun onBindViewHolder(holder: FeedViewHolder, position: Int): Táto metóda prepojí dáta s ViewHolderom
. Konkrétne nastavuje obrázok a text pre zobrazenia v ViewHolderi
na základe dát na aktuálnej pozícii.
override fun getItemCount() = items.size: Táto metóda vracia celkový počet položiek v dátovom zozname.
fun updateItems(newItems: List<MyItem>): Táto verejná metóda umožňuje aktualizovať zoznam položiek v adaptéri a informovať RecyclerView
o zmene dát prostredníctvom volania notifyDataSetChanged()
.
Kód je dobre štrukturovaný a každá časť má svoju zodpovednú úlohu pri zobrazovaní dát v RecyclerView
. Metóda updateItems
je obzvlášť užitočná, pretože umožňuje adaptéru pracovať s najnovšími dátami.
Krok 4: Inicializácia RecyclerView v Fragment
val recyclerView = view.findViewById<RecyclerView>(R.id.feed_recyclerview) recyclerView.layoutManager = LinearLayoutManager(context) val feedAdapter = FeedAdapter() recyclerView.adapter = feedAdapter feedAdapter.updateItems(listOf( MyItem(R.drawable.baseline_feed_24,"Prvy"), MyItem(R.drawable.baseline_map_24,"Druhy"), MyItem(R.drawable.baseline_account_box_24,"Treti"), ))
Tento úsek kódu ilustruje, ako sa inicializuje RecyclerView
a nastavuje sa jeho adaptér a správca rozloženia v kontexte Android aplikácie. Tu je podrobný opis krokov:
- val recyclerView = view.findViewById<RecyclerView>(R.id.feed_recyclerview): Táto línia kódu vyhľadáva
RecyclerView
v aktuálnom zobrazení/layoute pomocou jeho ID. Následne priradzuje referenciu na tentoRecyclerView
do premennejrecyclerView
. - recyclerView.layoutManager = LinearLayoutManager(context): Nastavuje správcu rozloženia pre
RecyclerView
.LinearLayoutManager
zobrazuje položky v lineárnom zozname, čo je štandardný spôsob zobrazenia položiek v zozname alebo mriežke v Android aplikáciách. - val feedAdapter = FeedAdapter(): Vytvára novú inštanciu adaptéra
FeedAdapter
, ktorý bol predtým definovaný. Tento adaptér bude zodpovedný za dodávanie zobrazení položiek preRecyclerView
. - recyclerView.adapter = feedAdapter: Priradzuje adaptér
feedAdapter
kRecyclerView
. Týmto sa zabezpečí, že každá položka v zozname bude mať správne zobrazenie, a bude správne zobrazovaná vRecyclerView
. - feedAdapter.updateItems(listOf( MyItem(R.drawable.baseline_feed_24,"Prvy"), MyItem(R.drawable.baseline_map_24,"Druhy"), MyItem(R.drawable.baseline_account_box_24,"Treti"), )): Tento kód aktualizuje dáta v adaptéri s novým zoznamom položiek. Každá položka je reprezentovaná inštanciou
MyItem
, ktorá obsahuje obrázok a text.updateItems
je metóda definovaná v našomFeedAdapter
, ktorá aktualizuje zoznam položiek a informuje adaptér, že dáta sa zmenili.
Tento kód je kľúčový pri inicializácii a nastavení RecyclerView
v Android aplikácii, aby sa zobrazovali položky v zozname pomocou custom adaptéra.
LinearLayoutManager je správca rozloženia, ktorý usporiada položky v lineárnej sekvencii. Je jedným z najčastejšie používaných správcov rozloženia v `RecyclerView` a poskytuje jednoduché zobrazenie položiek, buď horizontálne alebo vertikálne. Jeho hlavným cieľom je zobraziť položky v jednom stĺpci alebo riadku, podobne ako tradičný zoznam.
GridLayoutManager umožňuje zobraziť položky v mriežkovom formáte. V závislosti od orientácie a definovaného počtu "spanov" môže tento správca rozloženia usporiadať položky vo viacerých stĺpcoch (vertikálna orientácia) alebo riadkoch (horizontálna orientácia). Je ideálny pre situácie, keď chcete zobraziť položky v mriežkovom formáte, ako sú galérie obrázkov alebo aplikácie s dlaždicovým rozhraním.
Všeobecné vlastnosti
- Flexibilita: Oba správcovia rozloženia sú flexibilné a môžu byť prispôsobené rôznym potrebám zobrazenia. Ich orientácia, rozmer a ďalšie vlastnosti môžu byť nastavené podľa požiadaviek aplikácie.
- Optimalizácia: Ako súčasť knižnice RecyclerView, oba správcovia rozloženia sú navrhnuté tak, aby boli výkonné a optimalizované pre veľké súbory dát. Položky, ktoré nie sú viditeľné, sa opätovne použijú, čo znižuje záťaž na systém pri posúvaní.
- Pripojenie s adaptérom: Oba správcovia rozloženia pracujú v tesnej spolupráci s adaptérom, ktorý poskytuje dáta a definuje, ako sú jednotlivé položky zobrazené.
LinearLayoutManager
LinearLayoutManager
je jedným z manažérov rozloženia poskytovaných v rámci knižnice RecyclerView v Androide. Jeho hlavným účelom je zobraziť súbor položiek v lineárnom rozložení, čo môže byť vertikálne alebo horizontálne. Tu je niekoľko kľúčových bodov, ktoré je dôležité vedieť o LinearLayoutManager
:
- Základné Rozloženie:
LinearLayoutManager
umožňuje položkám v RecyclerView zobrazovať sa v priamke alebo lineárnej sekvencii, podobne ako LinearLayout v klasických Android rozloženiach. - Vertikálne alebo Horizontálne: Môžete nastaviť orientáciu LinearLayoutManagera na vertikálnu alebo horizontálnu. Vertikálna orientácia zobrazuje položky zhora nadol, kým horizontálna orientácia zobrazuje položky zľava doprava.
- Práca s RecyclerView: Aby RecyclerView mohol správne fungovať, potrebuje manažéra rozloženia.
LinearLayoutManager
je často používaný, keď chcete zobraziť položky ako jednoduchý jeden stĺpec alebo riadok. - Účinnosť:
LinearLayoutManager
recykluje iba tie položky, ktoré momentálne nie sú viditeľné na obrazovke, čím zvyšuje výkon pri posúvaní tým, že znovu používa zobrazenia. - Prispôsobivosť: Napriek svojej jednoduchosti je
LinearLayoutManager
veľmi prispôsobivý. Môže byť použitý v rôznych situáciách, kde je potrebné zobraziť zoznam položiek lineárne.
LinearLayoutManager
je dôležitou súčasťou mnohých Android aplikácií, ktoré vyžadujú zobrazenie zoznamu položiek v konzistentnom a účinnom spôsobe. Jeho použitie zjednodušuje správu rozloženia položiek v RecyclerView.
Príklad nastavenia LinearLayoutManager:
val layoutManager = LinearLayoutManager(context)
recyclerView.layoutManager = layoutManager
Vertikálna a horizontálna orientácia:
Ak chcete zmeniť orientáciu na horizontálnu, môžete to urobiť takto:
layoutManager.orientation = LinearLayoutManager.HORIZONTAL
GridLayoutManager
GridLayoutManager
je ďalší manažér rozloženia poskytovaný v rámci knižnice RecyclerView v Androide, ktorý zobrazuje položky v mriežkovom rozložení. Položky sú usporiadané v stĺpcoch a riadkoch, čo poskytuje vizuálne bohatší dojem ako lineárne rozloženie. Tu je niekoľko dôležitých aspektov, ktoré je dobré poznať o GridLayoutManager
:
- Mriežkové Rozloženie:
GridLayoutManager
rozdeľuje súbor položiek do mriežky, ktorá pozostáva zo stĺpcov a riadkov. Každý riadok obsahuje fixný počet stĺpcov. - Prispôsobiteľný Počet Stĺpcov: Môžete nastaviť počet stĺpcov v mriežke, čo je užitočné pre rôzne veľkosti displejov alebo orientácie zariadenia (na stojato alebo na ležato).
- Integrácia s RecyclerView: Podobne ako LinearLayoutManager, aj GridLayoutManager je používaný s RecyclerView pre zobrazenie položiek, ale poskytuje mriežkové rozloženie namiesto lineárneho.
- Recyklácia Zobrazení:
GridLayoutManager
tiež recykluje zobrazenia tým, že opätovne používa položky, ktoré sa stali neviditeľnými v dôsledku posúvania. - Flexibilita: Je možné prispôsobiť veľkosti položiek, meniť orientáciu rozloženia a dokonca umožniť rôzne typy zobrazení v rámci jednej mriežky s použitím
GridLayoutManager
.
GridLayoutManager
je ideálny pre aplikácie, ktoré potrebujú zobraziť položky v mriežkovom formáte, ako sú galérie obrázkov alebo komplexnejšie rozhrania. Poskytuje flexibilitu a vysoký výkon pre interaktívne a vizuálne prvky aplikácie.
Príklad nastavenia GridLayoutManager s 3 stĺpcami:
val gridLayoutManager = GridLayoutManager(context, 3)
recyclerView.layoutManager = gridLayoutManager
Ak chcete zmeniť orientáciu na horizontálnu a určiť počet riadkov, môžete to urobiť takto:
gridLayoutManager.orientation = GridLayoutManager.HORIZONTAL
// Uvedený počet riadkov je len príklad
gridLayoutManager.spanCount = 2
Rozdiely medzi LinearLayoutManager a GridLayoutManager
- Usporiadanie: LinearLayoutManager usporiada položky vertikálne alebo horizontálne v jednom stĺpci alebo riadku. Na druhej strane, GridLayoutManager môže usporiadať položky vo viacerých stĺpcoch alebo riadkoch.
- Vzhľad: Ak chcete zobraziť položky v klasickom zozname, použite LinearLayoutManager. Ak chcete zobraziť položky v mriežkovom formáte, použite GridLayoutManager.
- Flexibilita: GridLayoutManager je flexibilnejší v tom, že umožňuje zobrazenie položiek v mriežke s rôznym počtom stĺpcov alebo riadkov v závislosti od orientácie.
Vyberanie medzi LinearLayoutManager
a GridLayoutManager
závisí od špecifických potrieb vašej aplikácie a typu dát, ktoré chcete zobraziť. Zatiaľ čo LinearLayoutManager
je jednoduchší a ľahší na implementáciu, GridLayoutManager
poskytuje väčšiu vizuálnu flexibilitu a je lepší pre komplexnejšie rozvrhnutia.
Krok 5: Naplnenie dát do RecyclerView
myAdapter.updateItems(newData)
Aktualizácia zoznamu dát vo vašej aplikácii je bežnou požiadavkou, keď dáta podliehajú zmene alebo sú dynamicky načítané. V RecyclerView v Androide môžeme aktualizovať adaptér s novými položkami pomocou metódy, ako je myAdapter.updateItems(newData)
. Tu je podrobný opis tohto procesu:
- Definícia Metódy: V našom adaptéri
RecyclerView
definujeme metóduupdateItems
, ktorá prijíma zoznam nových dát. Táto metóda nahradí staré dáta novými. - Nahradenie Dát: V metóde
updateItems
nastavíme aktuálne dáta adaptéra na nový zoznam, ktorý je prenesený ako parameter. Toto prepíše existujúce dáta. - Notifikácia o Zmene Dát: Po aktualizácii dát je dôležité zavolať metódu
notifyDataSetChanged()
, aby bol adaptér informovaný o zmene dát a aby mohol obnoviť zobrazené položky. - Vizualizácia Aktualizácií: Keď je metóda
notifyDataSetChanged()
zavolaná,RecyclerView
znovu vyvolá metóduonBindViewHolder
pre položky, ktoré sú viditeľné, čím sa aktualizuje obsah zobrazený užívateľovi. - Optimalizácia Výkonu: Metóda
notifyDataSetChanged()
môže byť náročná na výkon, pretože spôsobuje prekreslenie všetkých položiek vRecyclerView
. Na optimalizáciu výkonu môžete použiť metódy, ako súnotifyItemInserted()
,notifyItemRemoved()
, atď., ktoré oznámia zmene iba konkrétnych položiek.
Metóda updateItems(newData)
je esenciálna pre udržanie údajov v RecyclerView
aktuálnymi. Správna implementácia tejto metódy a efektívne oznámenie zmien adaptéru zabezpečia hladkú a reaktívnu užívateľskú skúsenosť.
Metódy `notifyDataSetChanged()` a ich variácie
Informuje `RecyclerView` o tom, že sa zmenili údaje v celom datasete a môže spôsobiť znovu vykreslenie celého zoznamu. Táto metóda je považovaná za výkonnostne náročnú, pretože môže invalidovať všetky položky a znovu ich vykresliť, aj keď sa zmenila iba jedna položka.
2. notifyItemChanged(int position)Táto metóda informuje `RecyclerView` o zmene v jednej položke na špecifikovanej pozícii. Je efektívnejšia ako `notifyDataSetChanged()`, pretože aktualizuje iba danú položku, a nie celý zoznam.
3. notifyItemInserted(int position)Informuje `RecyclerView` o tom, že bola na špecifikovanej pozícii vložená nová položka. Používa sa, keď chceme pridať novú položku do datasetu.
4. notifyItemRemoved(int position)Informuje `RecyclerView` o tom, že položka na špecifikovanej pozícii bola odstránená. Používa sa, keď chceme odstrániť položku z datasetu.
5. notifyItemRangeChanged(int positionStart, int itemCount)Táto metóda informuje `RecyclerView` o zmene v určenom rozsahu položiek. Je užitočná, keď sa naraz mení viac položiek.
Význam a využitieMetódy `notify...` sú dôležité pre správnu aktualizáciu zobrazenia v `RecyclerView` po zmene údajov. Zabezpečujú, že používateľ vidí aktuálne údaje a zároveň optimalizujú výkonnosť tým, že obmedzujú vykresľovanie iba na zmenené položky. Odporúča sa vždy používať najšpecifikovanejšiu metódu, ktorá najlepšie zodpovedá zmene v údajoch, aby sa predišlo zbytočnému vykresľovaniu a zlepšila sa výkonnosť aplikácie.
Pre tých, ktorí chcú optimalizovať aktualizácie zoznamu v `RecyclerView.Adapter`, je možné použiť `DiffUtil`. Táto trieda vypočíta rozdiely medzi starým a novým zoznamom a automaticky aktualizuje adaptér s príslušnými animáciami.
DiffUtil
je nástroj v knižnici RecyclerView, ktorý pomáha optimalizovať aktualizáciu dát v adaptéri zlepšením výkonu a efektívnosti. Konkrétne DiffUtil.ItemCallback
sa používa na porovnanie položiek v zozname a identifikáciu zmien, ktoré treba aplikovať. Tu je podrobný opis, ako to funguje s ilustračným kódom:
- Vytvorenie DiffCallback: Vytvoríme triedu, ktorá rozširuje
DiffUtil.Callback
, ako je ukázané voMyItemDiffCallback
. Táto trieda definuje logiku porovnávania položiek. - Metódy Porovnávania: Implementujeme metódy
getOldListSize
,getNewListSize
,areItemsTheSame
aareContentsTheSame
pre porovnanie starej a novej kolekcie položiek. - Vypočítanie Rozdielov: Používame
DiffUtil.calculateDiff
na vypočítanie najefektívnejšieho súboru operácií, ktoré prevedú starý zoznam na nový. - Aktualizácia Adaptéra: Po vypočítaní rozdielov aktualizujeme dáta v adaptéri a použijeme
dispatchUpdatesTo
na aplikovanie týchto zmien na adaptér.
Vďaka použitiu DiffUtil
, adaptér vie presne, ktoré položky boli pridané, odstránené, alebo zmenené. To znižuje množstvo zbytočných operácií a zlepšuje výkon zobrazenia zoznamu, čím sa zároveň zvyšuje hladkosť a reaktívnosť užívateľského rozhrania.
- areItemsTheSame: Táto metóda kontroluje, či sú dve položky rovnaké. Je to prvý krok pri porovnávaní dvoch objektov. Metóda porovnáva, či je identifikátor alebo nejaký iný jedinečný ukazovateľ rovnaký pre oba objekty. Ak sú identifikátory rovnaké, znamená to, že ide o rovnakú položku.
- areContentsTheSame: Ak metóda
areItemsTheSame
vrátitrue
,DiffUtil
potom voláareContentsTheSame
, aby zistil, či majú rovnaké položky aj rovnaké údaje. Táto metóda skúma, či sa obsah položiek zmenil. Ak sa obsah nezmenil, metóda by mala vrátiťtrue
; v opačnom prípade vrátifalse
.
V praxi, areItemsTheSame
môže porovnávať identifikátory (alebo niektoré ine unikátne kľúče) položiek, zatiaľ čo areContentsTheSame
môže porovnávať skutočný obsah. To umožňuje DiffUtil
efektívne identifikovať a spracovať pridané, odstránené alebo zmenené položky.
Príklad použitia `DiffUtil` v `RecyclerView.Adapter`:
class MyAdapter : RecyclerView.Adapter<MyViewHolder>() { private var items: List<MyItem> = listOf() fun updateItems(newItems: List<MyItem>) { val diffCallback = MyItemDiffCallback(items, newItems) val diffResult = DiffUtil.calculateDiff(diffCallback) items = newItems diffResult.dispatchUpdatesTo(this) } // ... Zvyšok vášho kódu adaptéra ... } class MyItemDiffCallback( private val oldList: List<MyItem>, private val newList: List<MyItem> ) : DiffUtil.Callback() { override fun getOldListSize() = oldList.size override fun getNewListSize() = newList.size override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { return oldList[oldItemPosition].id == newList[newItemPosition].id } override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { return oldList[oldItemPosition] == newList[newItemPosition] } }
Použitím `DiffUtil`, môžete získať výhody automatických animácií a optimalizovaných aktualizácií, aj keď používate štandardný `RecyclerView.Adapter` namiesto `ListAdapter`.
Nezabudnite, ze je nevyhnutne upravit aj triedu MyItem v adaptri.
data class MyItem(val id: Int, val imageResource: Int, val text: String) { override fun equals(other: Any?): Boolean { if (this === other) return true if (javaClass != other?.javaClass) return false other as MyItem if (id != other.id) return false if (imageResource != other.imageResource) return false if (text != other.text) return false return true } override fun hashCode(): Int { var result = id result = 31 * result + imageResource result = 31 * result + text.hashCode() return result } }
Odporúčané linky
Najmä tieto Codelaby: