ListView: ce este, liste simple în aplicațiile Android

Autor: IT Sectr Publicat: 2026-02-23 Timp de citire: 8 min

ListView — componenta de bază Android pentru afișarea listelor verticale, disponibilă de la API 1 (Android 1.0). ListView creează o listă de elemente cu ajutorul ArrayAdapter și suportă machete personalizate de celule. Aflăm ce este ListView, cum să-l configurăm și ce capcane ascunde această componentă veche, dar încă utilizată. În IT Sectr întâlnim ListView în proiecte legacy și suținem compatibilitatea inversă cu Android 4.4. Pentru comparație cu alternativa modernă citiți articolul despre RecyclerView.

Principalele

  • ListView — componentă încorporată Android SDK pentru liste verticale, apărută în Android 1.0.
  • ArrayAdapter — adaptor standard pentru legarea unui tablou de date la ListView prin toString() sau machetă personalizată.
  • SimpleAdapter — adaptor pentru liste din date Map, comod pentru ecrane simple fără ViewModel.
  • onItemClickListener — handler de click încorporat care nu necesită implementare suplimentară în adaptor.
  • convertView — mecanism de reutilizare a View în ListView, pe care dezvoltatorul trebuie să-l implementeze manual (analog ViewHolder).

Ce este ListView în Android?

ListView — este un grup View din pachetul android.widget, destinat afișării unei liste derulabile de elemente. ListView implementează pattern-ul AdapterView: datele sunt transmise prin adaptor (Adapter), care convertește elementele de date în View afișate pe ecran. ListView există în Android SDK de la prima versiune (API 1) și nu necesită biblioteci suplimentare.

Arhitectura ListView este mai simplă decât RecyclerView: LayoutManager este încorporat (doar derulare verticală), animația modificărilor lipsește, separatoarele se stabilesc prin atributul XML android:divider. ListView adaugă automat OverScrollView și evidențiere la focalizare, ceea ce simplifică prototiparea. Conform datelor Statista (2025), aproximativ 15% din aplicațiile Android din top-100 Play Store conțin încă ListView — în principal proiecte legacy cu suport minim.

Istorie și actualitate

ListView a fost componenta principală de liste în Android din 2008 până în 2014, când la Google I/O 2014 a fost prezentat RecyclerView. În ciuda statutului parțial învechit (soft-deprecated), ListView rămâne disponibil în toate versiunile Android și nu este marcat ca @Deprecated în SDK API 35. Dacă proiectul dumneavoastră suportă Android 4.4 (API 19) și mai jos, ListView este singura alegere încorporată, deoarece RecyclerView necesită AndroidX și dependințe gradle.

Tipuri de adaptoare: ArrayAdapter și SimpleAdapter

ArrayAdapter — cel mai popular adaptor pentru ListView. Acesta acceptă List<T> și o machetă pentru fiecare element. În mod implicit ArrayAdapter apelează toString() pentru fiecare obiect și afișează textul în simple_list_item_1 (un TextView). Pentru afișare personalizată trebuie suprascris getView() sau transmisă o machetă personalizată în constructor.

kotlin
// ListView cu ArrayAdapter (text simplu)
class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    private val countries = listOf(
        "Rusia", "SUA", "Germania",
        "Franța", "Japonia", "China", "Brazilia"
    )

    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

        // Gestionarea click-ului
        binding.listView.onItemClickListener =
            AdapterView.OnItemClickListener { _, _, position, _ ->
                Toast.makeText(this, countries[position], Toast.LENGTH_SHORT).show()
            }
    }
}

SimpleAdapter este destinat listelor din date Map. Acesta acceptă List<Map<String, Any>> și un tablou from/to pentru legarea cheilor Map cu ID-urile widget-urilor din machetă. SimpleAdapter este comod pentru prototipuri rapide când nu este nevoie de o clasă separată de adaptor. Dezavantaj — lipsa tipizării type-safe și complexitatea cu logică personalizată.

xml
<!-- Machetă cu ListView -->
<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>

Crearea unui adaptor personalizat cu ViewHolder

Adaptorul personalizat pentru ListView suprascrie metoda getView(), pe care RecyclerView o împarte în onCreateViewHolder + onBindViewHolder. În ListView ambii pași sunt combinați, de aceea dezvoltatorul trebuie să implementeze independent pattern-ul ViewHolder prin convertView (View reutilizabil) și tag setTag().

kotlin
// Model de date
data class Product(
    name: String,
    price: String,
    imageResId: Int
)

// Adaptor personalizat cu ViewHolder
class ProductAdapter(
    context: Context,
    private val products: List<Product>
) : ArrayAdapter<Product>(context, 0, products) {

    // ViewHolder pentru cache
    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
    }
}

Diferența cheie de RecyclerView: în ListView metoda getView() este apelată pentru fiecare apariție a elementului pe ecran. Dacă nu se utilizează convertView și ViewHolder, fiecare derulare creează un nou obiect View, ceea ce duce la scurgeri de memorie și lag-uri pe liste cu 50+ elemente. ViewHolder cu view.tag — optimizare obligatorie pentru ListView cu machete personalizate.

Limitări ListView: de ce Google recomandă RecyclerView

ListView are patru limitări arhitecturale pe care Google le-a remediat în RecyclerView: (1) doar orientare verticală — fără grile, liste orizontale sau cascade; (2) lipsa notificărilor punctuale — orice modificare a datelor cauzează o redesenare completă prin notifyDataSetChanged(), ceea ce creează sacadări; (3) fără animație încorporată de adăugare/ștergere a elementelor; (4) fără separare a responsabilităților — LayoutManager este încorporat, ItemAnimator lipsește.

xml
<!-- item_product.xml — macheta elementului ListView -->
<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>

Consecințe practice: pe liste de până la 20 de elemente ListView funcționează la fel de rapid ca RecyclerView. La 100+ elemente diferența devine vizibilă: ListView începe să piardă FPS din cauza lipsei calculelor diferențiale și a ViewHolder forțat. Pentru liste cu actualizări frecvente (chat, feed, loguri) ListView nu este potrivit — utilizați RecyclerView cu Paging 3. În IT Sectr migrăm ListView pe RecyclerView la orice lucru pe ecrane legacy cu mai mult de 50 de elemente.

Configurarea ListView prin atribute XML

ListView oferă un set de atribute XML pentru configurare rapidă fără cod: android:divider (culoarea/desenul separatorului), android:dividerHeight (grosimea), android:scrollbars (bare de derulare), android:fastScrollEnabled (derulare rapidă prin mâner), android:choiceMode (mod de selecție: singleChoice, multipleChoice). Atributul android:entries permite popularea listei dintr-un tablou de resurse (string-array) fără adaptor.

AtributDescriereValoare exemplu
android:dividerCuloarea sau drawable-ul separatorului@color/gray_light
android:dividerHeightGrosimea separatorului în px/dp1dp
android:entriesTablou de șiruri din resurse@array/countries
android:choiceModeMod de selecție a elementuluisingleChoice
android:fastScrollEnabledDerulare rapidătrue
android:overlapAnchorAncoră pentru liste derulante (API 21+)true

Mod de selecție: choiceMode="singleChoice" activează stilul RadioButton, la care elementul selectat este evidențiat. choiceMode="multipleChoice" — casete de bifare pentru mai multe elemente. Datele de selecție sunt accesibile prin listView.checkedItemPosition sau listView.checkedItemIds. Important: la choiceMode ListView utilizează StateListDrawable pentru fundal — setați propriul selector dacă albastrul standard nu se potrivește cu designul.

ListView vs RecyclerView: compararea capacităților

Alegerea între ListView și RecyclerView depinde de cerințele proiectului. RecyclerView este standardul modern, dar ListView poate fi justificat pentru ecrane simple cu costuri minime de întreținere a codului vechi. Comparație după toți parametrii cheie:

ParametruListViewRecyclerView
Dimensiunea biblioteciiÎncorporat în SDK (≈60 KB)AndroidX (≈300 KB cu dependențe)
Versiunea minimăAPI 1API 14 (prin AndroidX)
OrientareDoar verticalăVerticală, orizontală, grilă, cascadă
ViewHolderImplementare manualăObligatoriu prin arhitectură
AnimațieDoar tranziții fadeDefaultItemAnimator (add, remove, move, change)
Actualizări punctualeNu (doar notifyDataSetChanged)notifyItemInserted/Removed/Changed
Click listeneronItemClickListener (încorporat)Prin ViewHolder (fără încorporat)
PerformanțăSuficientă pentru liste de până la 50 elemente60 FPS stabil pentru 1000+ elemente

Concluzie: pentru proiecte noi utilizați RecyclerView. ListView lăsați doar în codul legacy unde migrarea este nejustificat de costisitoare. Conform ghidurilor Material Design 3 (2026), listele de orice complexitate ar trebui să utilizeze RecyclerView pentru a corespunde standardelor moderne de performanță și accesibilitate.

Întrebări frecvente

ListView este învechit sau nu?

ListView nu este marcat ca @Deprecated în Android SDK API 35, dar Google nu recomandă utilizarea lui în proiecte noi (soft-deprecated). Componenta rămâne funcțională în toate versiunile Android. RecyclerView este înlocuitorul oficial din 2014. Dacă începeți un proiect nou — alegeți RecyclerView. Dacă întrețineți unul existent — ListView va continua să funcționeze fără modificări.

Cum se adaugă header/footer la ListView?

ListView suportă metodele addHeaderView(View, Object, boolean) și addFooterView(View, Object, boolean). Header și footer se adaugă în lista generală de elemente, dar nu participă în adaptor — ele se afișează întotdeauna la începutul și sfârșitul listei. Important: adăugați header/footer înainte de setarea adaptorului (setAdapter()), altfel nu vor fi luate în considerare. După adăugarea header, ID-urile pozițiilor elementelor se deplasează cu numărul de header-e.

De ce ListView nu derulează în interiorul ScrollView?

ListView și ScrollView ambele procesează gesturi verticale, ceea ce creează un conflict: ScrollView exterior interceptează derularea, iar ListView nu se derulează. Soluție: (1) nu încorporați ListView în ScrollView — utilizați RecyclerView cu NestedScrollingChild, (2) înlocuiți ScrollView cu NestedScrollView (API 21+), (3) utilizați ListView cu înălțime fixă (android:layout_height="...dp") în interiorul ScrollView, dar aceasta va sparge adaptabilitatea.

Cum se curăță ListView și se actualizează datele?

Curățarea datelor în ListView depinde de tipul adaptorului. Pentru ArrayAdapter: adapter.clear() și adapter.addAll(newList) urmate de adapter.notifyDataSetChanged(). Pentru adaptor personalizat: actualizați lista de date și apelați notifyDataSetChanged(). Atenție: listView.invalidateViews() doar redesenează View, dar nu actualizează datele. Modificați întotdeauna datele prin adaptor, nu direct.

Cum se modifică înălțimea elementului ListView?

Înălțimea elementului ListView se stabilește în macheta item. Dacă macheta utilizează layout_height="wrap_content", înălțimea se ajustează după conținut. Pentru înălțime fixă a tuturor elementelor utilizați un adaptor personalizat care stabilește LayoutParams în getView(): view.layoutParams.height = resources.getDimensionPixelSize(R.dimen.itemHeight). Pentru înălțimi eterogene utilizați RecyclerView cu tipuri de vizualizare diferite.

Concluzii

  • ListView — componenta de bază Android SDK pentru liste verticale, disponibilă de la API 1.
  • ArrayAdapter — cel mai simplu adaptor pentru o listă de șiruri; pentru machete personalizate este necesar getView() suprascris.
  • ViewHolder în ListView se implementează manual prin convertView și view.tag — condiție obligatorie de performanță.
  • ListView suportă choiceMode (single/multiple), header/footer, fastScroll și android:entries fără adaptor.
  • Limitări ListView: doar orientare verticală, lipsa animației, redesenare completă la orice modificare.
  • ListView nu este marcat ca învechit, dar Google recomandă RecyclerView pentru toate proiectele noi.
  • Pentru liste de până la 50 de elemente ListView este suficient; pentru orice mai complex — utilizați RecyclerView.

Vom dezvolta o aplicație mobilă la cheie

IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.

Discutați proiectul

Citiți și