ListView: шта је то, једноставне листе у Android апликацијама

Аутор: IT Sectr Објављено: 2026-02-23 Време читања: 8 мин

ListView — основна Android компонента за приказ вертикалних листи, доступна од API 1 (Android 1.0). ListView креира листу елемената помоћу ArrayAdapter-а и подржава прилагођене изгледе ћелија. Разјашњавамо шта је ListView, како га подесити и какве замке крије ова стара, али још увек коришћена компонента. У IT Sectr-у сусрећемо ListView у legacy пројектима и одржавамо уназад компатибилност са Android 4.4. За поређење са савременом алтернативом прочитајте чланак о RecyclerView-у.

Главно

  • ListView — уграђена Android SDK компонента за вертикалне листе, доступна од Android 1.0.
  • ArrayAdapter — стандардни адаптер за повезивање низа података са ListView-ом путем toString() или прилагођеног изгледа.
  • SimpleAdapter — адаптер за листе из Map података, погодан за једноставне екране без ViewModel-а.
  • onItemClickListener — уграђени обрађивач кликова који не захтева додатну имплементацију у адаптеру.
  • convertView — механизам поновног коришћења View-а у ListView-у, који програмер мора ручно да имплементира (аналогно ViewHolder-у).

Шта је ListView у Android-у?

ListView — је View група из пакета android.widget, намењена за приказ помичне листе елемената. ListView имплементира образац AdapterView: подаци се преносе кроз адаптер (Adapter), који конвертује елементе података у View приказане на екрану. ListView постоји у Android SDK-у од прве верзије (API 1) и не захтева додатне библиотеке.

Архитектура ListView-а је једноставнија од RecyclerView-а: LayoutManager је уграђен (само вертикално померање), анимација промена не постоји, разделници се постављају кроз XML атрибут android:divider. ListView аутоматски додаје OverScrollView и истицање при фокусу, што поједностављује прототиповање. Према подацима Statista (2025), око 15% Android апликација у top-100 Play Store-а још увек садржи ListView — углавном legacy пројекти са минималном подршком.

Историја и актуелност

ListView је био главна компонента листи у Android-у од 2008. до 2014. године, када је на Google I/O 2014 представљен RecyclerView. Упркос статусу делимично застарелог (soft-deprecated), ListView остаје доступан у свим верзијама Android-а и није означен као @Deprecated у SDK API 35. Ако ваш пројекат подржава Android 4.4 (API 19) и ниже, ListView је једини уграђени избор, јер RecyclerView захтева AndroidX и gradle зависности.

Типови адаптера: ArrayAdapter и SimpleAdapter

ArrayAdapter — најпопуларнији адаптер за ListView. Он прихвата List<T> и изглед за сваки елемент. Подразумевано ArrayAdapter позива toString() за сваки објекат и приказује текст у simple_list_item_1 (један TextView). За прилагођени приказ потребно је прегазити getView() или проследити прилагођени изглед у конструктору.

kotlin
// ListView са ArrayAdapter-ом (једноставан текст)
class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    private val countries = listOf(
        "Русија", "САД", "Немачка",
        "Француска", "Јапан", "Кина", "Бразил"
    )

    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

        // Обрада клика
        binding.listView.onItemClickListener =
            AdapterView.OnItemClickListener { _, _, position, _ ->
                Toast.makeText(this, countries[position], Toast.LENGTH_SHORT).show()
            }
    }
}

SimpleAdapter је намењен за листе из Map података. Он прихвата List<Map<String, Any>> и низ from/to за повезивање кључева Map са ID-овима виџета у изгледу. SimpleAdapter је погодан за брзе прототипове када није потребна посебна класа адаптера. Недостатак — одсуство type-safe типизације и сложеност са прилагођеном логиком.

xml
<!-- Изглед са 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>

Креирање прилагођеног адаптера са ViewHolder-ом

Прилагођени адаптер за ListView прегази метод getView(), који RecyclerView раздваја на onCreateViewHolder + onBindViewHolder. У ListView-у оба корака су спојена, зато програмер мора сам да имплементира образац ViewHolder кроз convertView (поновно коришћени View) и tag setTag().

kotlin
// Модел података
data class Product(
    name: String,
    price: String,
    imageResId: Int
)

// Прилагођени адаптер са ViewHolder-ом
class ProductAdapter(
    context: Context,
    private val products: List<Product>
) : ArrayAdapter<Product>(context, 0, products) {

    // ViewHolder за кеширање
    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
    }
}

Кључна разлика од RecyclerView-а: у ListView-у метод getView() се позива за свако појављивање елемента на екрану. Ако се не користи convertView и ViewHolder, свако померање ствара нови View објекат, што доводи до цурења меморије и застоја на листама са 50+ елемената. ViewHolder са view.tag — обавезна оптимизација за ListView са прилагођеним изгледима.

Ограничења ListView-а: зашто Google препоручује RecyclerView

ListView има четири архитектурална ограничења која је Google исправио у RecyclerView-у: (1) само вертикална оријентација — нема мрежа, хоризонталних листи или каскада; (2) одсуство тачкастих обавештења — било која промена података изазива потпуно прецртавање путем notifyDataSetChanged(), што ствара трзаје; (3) нема уграђене анимације додавања/уклањања елемената; (4) нема раздвајања одговорности — LayoutManager је уграђен, ItemAnimator не постоји.

xml
<!-- item_product.xml — изглед елемента 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>

Практичне последице: на листама до 20 елемената ListView ради једнако брзо као RecyclerView. Код 100+ елемената разлика постаје приметна: ListView почиње да губи FPS због одсуства диф-прорачуна и присилног ViewHolder-а. За листе са честим ажурирањима (чет, феед, логови) ListView није погодан — користите RecyclerView са Paging 3. У IT Sectr-у мигрирамо ListView на RecyclerView при сваком раду на legacy екранима са више од 50 елемената.

Подешавање ListView-а кроз XML атрибуте

ListView пружа скуп XML атрибута за брзо подешавање без кода: android:divider (боја/цртеж разделника), android:dividerHeight (дебљина), android:scrollbars (траке за померање), android:fastScrollEnabled (брзо померање по ручици), android:choiceMode (режим избора: singleChoice, multipleChoice). Атрибут android:entries омогућава попуњавање листе из низа ресурса (string-array) без адаптера.

АтрибутОписПример вредности
android:dividerБоја или drawable разделника@color/gray_light
android:dividerHeightДебљина разделника у px/dp1dp
android:entriesНиз стрингова из ресурса@array/countries
android:choiceModeРежим избора елементаsingleChoice
android:fastScrollEnabledБрзо померањеtrue
android:overlapAnchorСидрашце за падајуће листе (API 21+)true

Режим избора: choiceMode="singleChoice" укључује RadioButton стил, при којем се изабрани елемент истиче. choiceMode="multipleChoice" — поља за потврду за више елемената. Подаци избора доступни су кроз listView.checkedItemPosition или listView.checkedItemIds. Важно: при choiceMode ListView користи StateListDrawable за позадину — поставите сопствени селектор ако стандардна плава не одговара дизајну.

ListView vs RecyclerView: поређење могућности

Избор између ListView-а и RecyclerView-а зависи од захтева пројекта. RecyclerView је савремени стандард, али ListView може бити оправдан за једноставне екране са минималним трошковима одржавања старог кода. Поређење по свим кључним параметрима:

ПараметарListViewRecyclerView
Величина библиотекеУграђен у SDK (≈60 KB)AndroidX (≈300 KB са зависностима)
Минимална верзијаAPI 1API 14 (путем AndroidX)
ОријентацијаСамо вертикалнаВертикална, хоризонтална, мрежа, каскада
ViewHolderРучна имплементацијаОбавезан по архитектури
АнимацијаСамо fade прелазиDefaultItemAnimator (add, remove, move, change)
Тачкаста ажурирањаНе (само notifyDataSetChanged)notifyItemInserted/Removed/Changed
Click listeneronItemClickListener (уграђен)Путем ViewHolder-а (нема уграђеног)
ПерформансеДовољне за листе до 50 елеменатаСтабилних 60 FPS за 1000+ елемената

Закључак: за нове пројекте користите RecyclerView. ListView оставите само у legacy коду где миграција није оправдано скупа. Према смерницама Material Design 3 (2026), листе било које сложености треба да користе RecyclerView за усаглашавање са савременим стандардима перформанси и доступности.

Често постављана питања

Да ли је ListView застарео или није?

ListView није означен као @Deprecated у Android SDK API 35, али Google не препоручује његово коришћење у новим пројектима (soft-deprecated). Компонента остаје функционална у свим верзијама Android-а. RecyclerView је званична замена од 2014. године. Ако започињете нови пројекат — изаберите RecyclerView. Ако одржавате постојећи — ListView ће наставити да ради без промена.

Како додати header/footer у ListView?

ListView подржава методе addHeaderView(View, Object, boolean) и addFooterView(View, Object, boolean). Header и footer се додају у општу листу елемената, али не учествују у адаптеру — увек се приказују на почетку и крају листе. Важно: додајте header/footer пре постављања адаптера (setAdapter()), иначе неће бити узети у обзир. Након додавања header-а, ID позиција елемената се померају за број header-а.

Зашто ListView не скролује унутар ScrollView-а?

ListView и ScrollView оба обрађују вертикалне гестове, што ствара конфликт: спољашњи ScrollView пресреће померање, а ListView се не помера. Решење: (1) не уграђујте ListView у ScrollView — користите RecyclerView са NestedScrollingChild, (2) замените ScrollView са NestedScrollView (API 21+), (3) користите ListView са фиксном висином (android:layout_height="...dp") унутар ScrollView-а, али то ће сломити прилагодљивост.

Како очистити ListView и ажурирати податке?

Чишћење података у ListView-у зависи од типа адаптера. За ArrayAdapter: adapter.clear() и adapter.addAll(newList) са накнадним adapter.notifyDataSetChanged(). За прилагођени адаптер: ажурирајте листу података и позовите notifyDataSetChanged(). Пажња: listView.invalidateViews() само прецртава View, али не ажурира податке. Увек мењајте податке кроз адаптер, а не директно.

Како променити висину елемента ListView-а?

Висина елемента ListView-а се поставља у изгледу item-разметке. Ако изглед користи layout_height="wrap_content", висина се прилагођава садржају. За фиксну висину свих елемената користите прилагођени адаптер који поставља LayoutParams у getView(): view.layoutParams.height = resources.getDimensionPixelSize(R.dimen.itemHeight). За различите висине користите RecyclerView са различитим типовима приказа.

Резиме

  • ListView — основна Android SDK компонента за вертикалне листе, доступна од API 1.
  • ArrayAdapter — најједноставнији адаптер за листу стрингова; за прилагођене изгледе потребан је прегажени getView().
  • ViewHolder у ListView-у се имплементира ручно кроз convertView и view.tag — обавезан услов перформанси.
  • ListView подржава choiceMode (single/multiple), header/footer, fastScroll и android:entries без адаптера.
  • Ограничења ListView-а: само вертикална оријентација, одсуство анимације, потпуно прецртавање при било којој промени.
  • ListView није означен као застарео, али Google препоручује RecyclerView за све нове пројекте.
  • За листе до 50 елемената ListView је довољан; за све што је сложеније — користите RecyclerView.

Развићемо мобилну апликацију под кључ

IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође