ListView: τι είναι, απλές λίστες σε εφαρμογές Android

Συγγραφέας: IT Sectr Δημοσιεύτηκε: 2026-02-23 Χρόνος ανάγνωσης: 8 λεπ

ListView — βασικό στοιχείο Android για εμφάνιση κάθετων λιστών, διαθέσιμο από API 1 (Android 1.0). Το ListView δημιουργεί λίστα από στοιχεία με τη βοήθεια του ArrayAdapter και υποστηρίζει προσαρμοσμένες διατάξεις κελιών. Κατανοούμε τι είναι το ListView, πώς να το ρυθμίσετε και ποιες παγίδες κρύβει αυτό το παλιό αλλά ακόμα χρησιμοποιούμενο στοιχείο. Στην IT Sectr συναντάμε το ListView σε κληρονομικά έργα και υποστηρίζουμε αντίστροφη συμβατότητα με 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 — κυρίως κληρονομικά έργα με ελάχιστη υποστήριξη.

Ιστορία και επικαιρότητα

Το 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 με IDs widget στη διάταξη. Το 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) και της ετικέτας 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. Για λίστες με συχνές ενημερώσεις (chat, feed, αρχεία καταγραφής) το ListView δεν είναι κατάλληλο — χρησιμοποιήστε RecyclerView με Paging 3. Στην IT Sectr μεταφέρουμε ListView σε RecyclerView σε κάθε εργασία σε κληρονομικές οθόνες με περισσότερα από 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 μόνο σε κληρονομικό κώδικα όπου η μετάβαση είναι αδικαιολόγητα δαπανηρή. Σύμφωνα με τις οδηγίες 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. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.

Συζήτηση έργου

Διαβάστε επίσης