ListView — alapvető Android komponens függőleges listák megjelenítéséhez, elérhető API 1-től (Android 1.0). A ListView elemekből hoz létre listát az ArrayAdapter segítségével, és támogatja az egyedi cella elrendezéseket. Megértjük, mi az a ListView, hogyan kell beállítani, és milyen buktatókat rejt ez a régi, de még mindig használt komponens. Az IT Sectr-ben a ListView-t örökölt projektekben találkozunk, és fenntartjuk a visszamenőleges kompatibilitást Android 4.4-gyel. A modern alternatívával való összehasonlításhoz olvassa el a RecyclerView-ról szóló cikket.
Főbb pontok
ListView — egy View csoport az android.widget csomagból, amely görgethető elem lista megjelenítésére szolgál. A ListView az AdapterView mintát implementálja: az adatok az adapteren (Adapter) keresztül kerülnek továbbításra, amely az adatelemeket a képernyőn megjelenített View-vé alakítja. A ListView az Android SDK-ban az első verziótól (API 1) kezdve létezik, és nem igényel további könyvtárakat.
Architektúrája a ListView-nak egyszerűbb, mint a RecyclerView-nek: a LayoutManager beépített (csak függőleges görgetés), a változások animációja hiányzik, az elválasztók az android:divider XML attribútumon keresztül állíthatók be. A ListView automatikusan hozzáadja az OverScrollView-t és a kiemelést fókuszáláskor, ami leegyszerűsíti a prototípuskészítést. A Statista (2025) adatai szerint a Play Store top-100-as Android alkalmazásainak körülbelül 15%-a még mindig tartalmaz ListView-t — főként minimális támogatású örökölt projektek.
A ListView volt a fő lista komponens Androidban 2008-tól 2014-ig, amikor a Google I/O 2014-en bemutatták a RecyclerView-t. A részben elavult (soft-deprecated) státusz ellenére a ListView továbbra is elérhető az Android összes verziójában, és nincs @Deprecated-ként jelölve az SDK API 35-ben. Ha a projektje támogatja az Android 4.4-et (API 19) és alacsonyabbakat, a ListView az egyetlen beépített választás, mivel a RecyclerView AndroidX-t és gradle függőségeket igényel.
ArrayAdapter — a legnépszerűbb adapter a ListView számára. Elfogad egy List<T>-t és egy elrendezést minden elemhez. Alapértelmezés szerint az ArrayAdapter meghívja a toString()-t minden objektumhoz, és megjeleníti a szöveget a simple_list_item_1-ben (egy TextView). Egyedi megjelenítéshez felül kell írni a getView()-t, vagy egyedi elrendezést kell átadni a konstruktorban.
// ListView ArrayAdapter-rel (egyszerű szöveg)
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private val countries = listOf(
"Oroszország", "USA", "Németország",
"Franciaország", "Japán", "Kína", "Brazília"
)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val adapter = ArrayAdapter<String>(
this,
android.R.layout.simple_list_item_1,
countries
)
binding.listView.adapter = adapter
// Kattintás kezelése
binding.listView.onItemClickListener =
AdapterView.OnItemClickListener { _, _, position, _ ->
Toast.makeText(this, countries[position], Toast.LENGTH_SHORT).show()
}
}
}
SimpleAdapter Map-adatokból álló listákhoz készült. Elfogad egy List<Map<String, Any>>-t és egy from/to tömböt a Map kulcsainak az elrendezés widgetjeinek ID-ival való összekapcsolásához. A SimpleAdapter kényelmes gyors prototípusokhoz, amikor nincs szükség külön adapter osztályra. Hátránya — a type-safe tipizálás hiánya és az egyedi logikával való bonyolultság.
<!-- Elrendezés ListView-val -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="@color/divider"
android:dividerHeight="1px"
android:scrollbars="vertical" />
</LinearLayout>
Egyedi adapter a ListView számára felülírja a getView() metódust, amelyet a RecyclerView onCreateViewHolder + onBindViewHolder részekre bont. A ListView-ban mindkét lépés össze van vonva, ezért a fejlesztőnek önállóan kell implementálnia a ViewHolder mintát a convertView (újrafelhasznált View) és a setTag() tagen keresztül.
// Adatmodell
data class Product(
name: String,
price: String,
imageResId: Int
)
// Egyedi adapter ViewHolder-rel
class ProductAdapter(
context: Context,
private val products: List<Product>
) : ArrayAdapter<Product>(context, 0, products) {
// ViewHolder a gyorsítótárazáshoz
private class ViewHolder(view: View) {
val nameText: TextView = view.findViewById(R.id.tvName)
val priceText: TextView = view.findViewById(R.id.tvPrice)
val imageView: ImageView = view.findViewById(R.id.ivProduct)
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val view = convertView ?: LayoutInflater.from(context)
.inflate(R.layout.item_product, parent, false)
.also { it.tag = ViewHolder(it) }
val holder = view.tag as ViewHolder
val product = getItem(position)
holder.nameText.text = product.name
holder.priceText.text = product.price
holder.imageView.setImageResource(product.imageResId)
return view
}
}
Kulcsfontosságú különbség a RecyclerView-tól: a ListView-ban a getView() metódus minden elem képernyőn való megjelenésekor meghívásra kerül. Ha nem használ convertView-t és ViewHolder-t, minden görgetés új View objektumot hoz létre, ami memóriaszivárgáshoz és akadozáshoz vezet a 50+ elemű listákon. A ViewHolder view.tag-gal — kötelező optimalizálás a ListView-hoz egyedi elrendezésekkel.
ListView négy architekturális korláttal rendelkezik, amelyeket a Google a RecyclerView-ban javított ki: (1) csak függőleges tájolás — nincsenek rácsok, vízszintes listák vagy kaszkádok; (2) pontszerű értesítések hiánya — bármilyen adatváltozás teljes újrarajzolást okoz a notifyDataSetChanged()-en keresztül, ami rángatást eredményez; (3) nincs beépített animáció elemek hozzáadásához/eltávolításához; (4) nincs felelősségi körök szétválasztása — a LayoutManager beépített, az ItemAnimator hiányzik.
<!-- item_product.xml — ListView elem elrendezése -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="12dp">
<ImageView
android:id="@+id/ivProduct"
android:layout_width="56dp"
android:layout_height="56dp"
android:scaleType="centerCrop" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:paddingStart="12dp">
<TextView
android:id="@+id/tvName"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:id="@+id/tvPrice"
android:textSize="14sp"
android:textColor="@color/price" />
</LinearLayout>
</LinearLayout>
Gyakorlati következmények: 20 elemű listákban a ListView ugyanolyan gyorsan működik, mint a RecyclerView. 100+ elemnél a különbség észrevehetővé válik: a ListView FPS-t kezd veszteni a differenciális számítások hiánya és a kényszerített ViewHolder miatt. Gyakran frissülő listákhoz (chat, feed, naplók) a ListView nem alkalmas — használjon RecyclerView-t Paging 3-mal. Az IT Sectr-ben a ListView-t RecyclerView-ra migráljuk minden olyan örökölt képernyőn, ahol 50-nél több elem van.
ListView XML attribútumok készletét kínálja gyors beállításhoz kód nélkül: android:divider (elválasztó színe/rajza), android:dividerHeight (vastagság), android:scrollbars (görgetősávok), android:fastScrollEnabled (gyors görgetés fogantyúval), android:choiceMode (kiválasztási mód: singleChoice, multipleChoice). Az android:entries attribútum lehetővé teszi a lista kitöltését erőforrás tömbből (string-array) adapter nélkül.
| Attribútum | Leírás | Példa érték |
|---|---|---|
| android:divider | Elválasztó színe vagy drawable | @color/gray_light |
| android:dividerHeight | Elválasztó vastagsága px/dp-ben | 1dp |
| android:entries | Karakterláncok tömbje erőforrásokból | @array/countries |
| android:choiceMode | Elem kiválasztási mód | singleChoice |
| android:fastScrollEnabled | Gyors görgetés | true |
| android:overlapAnchor | Horgony felugró listákhoz (API 21+) | true |
Kiválasztási mód: a choiceMode="singleChoice" RadioButton stílust aktivál, ahol a kiválasztott elem kiemelésre kerül. choiceMode="multipleChoice" — jelölőnégyzetek több elemhez. A kiválasztási adatok a listView.checkedItemPosition vagy listView.checkedItemIds segítségével érhetők el. Fontos: choiceMode esetén a ListView StateListDrawable-t használ a háttérhez — állítson be saját szelektort, ha az alapértelmezett kék nem illik a dizájnhoz.
Választás a ListView és a RecyclerView között a projekt követelményeitől függ. A RecyclerView modern szabvány, de a ListView indokolt lehet egyszerű képernyőkhöz minimális régi kód karbantartási költségekkel. Összehasonlítás az összes kulcsfontosságú paraméter alapján:
| Paraméter | ListView | RecyclerView |
|---|---|---|
| Könyvtár mérete | Beépített az SDK-ba (≈60 KB) | AndroidX (≈300 KB függőségekkel) |
| Minimális verzió | API 1 | API 14 (AndroidX-en keresztül) |
| Tájolás | Csak függőleges | Függőleges, vízszintes, rács, kaszkád |
| ViewHolder | Manuális implementáció | Architektúra által kötelező |
| Animáció | Csak fade átmenetek | DefaultItemAnimator (add, remove, move, change) |
| Pontszerű frissítések | Nem (csak notifyDataSetChanged) | notifyItemInserted/Removed/Changed |
| Click listener | onItemClickListener (beépített) | ViewHolder-en keresztül (nincs beépített) |
| Teljesítmény | Elegendő 50 elemű listákhoz | Stabil 60 FPS 1000+ elemhez |
Következtetés: új projektekhez használjon RecyclerView-t. A ListView-t csak olyan örökölt kódban hagyja, ahol a migráció indokolatlanul drága. A Material Design 3 (2026) irányelvei szerint a bármilyen összetettségű listáknak RecyclerView-t kell használniuk a modern teljesítmény- és hozzáférhetőségi szabványoknak való megfeleléshez.
Gyakran Ismételt Kérdések
ListView nincs @Deprecated-ként jelölve az Android SDK API 35-ben, de a Google nem ajánlja a használatát új projektekben (soft-deprecated). A komponens továbbra is működőképes az Android összes verziójában. A RecyclerView 2014 óta a hivatalos helyettesítő. Ha új projektet kezd — válassza a RecyclerView-t. Ha meglévőt tart fenn — a ListView továbbra is változtatás nélkül fog működni.
A ListView támogatja a addHeaderView(View, Object, boolean) és addFooterView(View, Object, boolean) metódusokat. A header és footer hozzáadásra kerül az elemek általános listájához, de nem vesznek részt az adapterben — mindig a lista elején és végén jelennek meg. Fontos: a header/footer-t az adapter beállítása előtt adja hozzá (setAdapter()), különben nem kerülnek figyelembevételre. A header hozzáadása után az elem pozíciók ID-i a headerek számával eltolódnak.
ListView és ScrollView mindketten függőleges gesztusokat dolgoznak fel, ami konfliktust okoz: a külső ScrollView elfogja a görgetést, és a ListView nem görgethető. Megoldás: (1) ne ágyazza be a ListView-t ScrollView-ba — használjon RecyclerView-t NestedScrollingChild-del, (2) cserélje ki a ScrollView-t NestedScrollView-ra (API 21+), (3) használjon rögzített magasságú (android:layout_height="...dp") ListView-t a ScrollView-n belül, de ez megtöri az alkalmazkodóképességet.
Az adatok törlése a ListView-ban az adapter típusától függ. ArrayAdapter esetén: adapter.clear() és adapter.addAll(newList) majd adapter.notifyDataSetChanged(). Egyedi adapter esetén: frissítse az adatlistát és hívja meg a notifyDataSetChanged()-t. Figyelem: a listView.invalidateViews() csak újrarajzolja a View-t, de nem frissíti az adatokat. Mindig az adapteren keresztül módosítsa az adatokat, ne közvetlenül.
A ListView elem magasságát az item elrendezésben állítják be. Ha az elrendezés layout_height="wrap_content"-t használ, a magasság a tartalomhoz igazodik. Rögzített magassághoz használjon egyedi adaptert, amely beállítja a LayoutParams-t a getView()-ben: view.layoutParams.height = resources.getDimensionPixelSize(R.dimen.itemHeight). Különböző magasságokhoz használjon RecyclerView-t különböző nézet típusokkal.
Összefoglaló
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.
Olvassa el is