ListView: qué es, listas simples en aplicaciones Android

Autor: IT Sectr Publicado: 2026-02-23 Tiempo de lectura: 8 min

ListView es un componente básico de Android para mostrar listas verticales, disponible desde API 1 (Android 1.0). ListView crea una lista de elementos usando ArrayAdapter y admite diseños de celdas personalizados. Analicemos qué es ListView, cómo configurarlo y qué dificultades oculta este componente antiguo pero aún utilizado. En IT Sectr encontramos ListView en proyectos heredados y mantenemos compatibilidad con Android 4.4. Para una comparación con la alternativa moderna, lea el artículo sobre RecyclerView.

Puntos clave

  • ListView es un componente integrado del SDK de Android para listas verticales, introducido en Android 1.0.
  • ArrayAdapter es un adaptador estándar para vincular un array de datos a ListView mediante toString() o un diseño personalizado.
  • SimpleAdapter es un adaptador para listas de datos Map, conveniente para pantallas simples sin ViewModel.
  • onItemClickListener es un manejador de clics integrado que no requiere implementación adicional en el adaptador.
  • convertView es un mecanismo de reutilización de View en ListView que el desarrollador debe implementar manualmente (análogo a ViewHolder).

¿Qué es ListView en Android?

ListView es un ViewGroup del paquete android.widget diseñado para mostrar una lista desplazable de elementos. ListView implementa el patrón AdapterView: los datos se pasan a través de un adaptador (Adapter), que convierte los elementos de datos en Views mostrados en pantalla. ListView existe en el SDK de Android desde la primera versión (API 1) y no requiere bibliotecas adicionales.

Arquitectura de ListView es más simple que RecyclerView: LayoutManager está integrado (solo desplazamiento vertical), las animaciones de cambio están ausentes, los divisores se configuran mediante el atributo XML android:divider. ListView agrega automáticamente OverScrollView y resaltado de enfoque, lo que simplifica la creación de prototipos. Según Statista (2025), alrededor del 15% de las aplicaciones de Android en el top 100 de Play Store aún contienen ListView — principalmente proyectos heredados con soporte mínimo.

Historia y relevancia

ListView fue el componente principal de listas en Android desde 2008 hasta 2014, cuando se presentó RecyclerView en Google I/O 2014. A pesar de estar parcialmente obsoleto (soft-deprecated), ListView permanece disponible en todas las versiones de Android y no está marcado como @Deprecated en SDK API 35. Si tu proyecto admite Android 4.4 (API 19) o inferior, ListView es la única opción integrada, ya que RecyclerView requiere AndroidX y dependencias de Gradle.

Tipos de adaptadores: ArrayAdapter y SimpleAdapter

ArrayAdapter es el adaptador más popular para ListView. Acepta List<T> y un diseño para cada elemento. Por defecto, ArrayAdapter llama a toString() en cada objeto y muestra el texto en simple_list_item_1 (un TextView). Para visualización personalizada, debe sobrescribir getView() o pasar un diseño personalizado en el constructor.

kotlin
// ListView con ArrayAdapter (texto simple)
class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    private val countries = listOf(
        "Rusia", "EE.UU.", "Alemania",
        "Francia", "Japón", "China", "Brasil"
    )

    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

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

SimpleAdapter está diseñado para listas de datos Map. Acepta List<Map<String, Any>> y un array from/to para vincular claves de Map con IDs de widgets en el diseño. SimpleAdapter es conveniente para prototipos rápidos cuando no se necesita una clase de adaptador separada. La desventaja es la falta de tipado seguro y la complejidad con lógica personalizada.

xml
<!-- Diseño con 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>

Creación de un adaptador personalizado con ViewHolder

Adaptador personalizado para ListView sobrescribe el método getView(), que RecyclerView divide en onCreateViewHolder + onBindViewHolder. En ListView, ambos pasos están combinados, por lo que el desarrollador debe implementar independientemente el patrón ViewHolder usando convertView (View reutilizable) y el método setTag().

kotlin
// Modelo de datos
data class Product(
    name: String,
    price: String,
    imageResId: Int
)

// Adaptador personalizado con ViewHolder
class ProductAdapter(
    context: Context,
    private val products: List<Product>
) : ArrayAdapter<Product>(context, 0, products) {

    // ViewHolder para almacenamiento en caché
    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
    }
}

Diferencia clave con RecyclerView: en ListView, el método getView() se llama cada vez que un elemento aparece en pantalla. Si no se usan convertView y ViewHolder, cada desplazamiento crea un nuevo objeto View, lo que provoca pérdidas de memoria y retrasos en listas con más de 50 elementos. ViewHolder con view.tag es una optimización obligatoria para ListView con diseños personalizados.

Limitaciones de ListView: por qué Google recomienda RecyclerView

ListView tiene cuatro limitaciones arquitectónicas que Google solucionó en RecyclerView: (1) solo orientación vertical — sin cuadrículas, listas horizontales o diseños escalonados; (2) sin notificaciones detalladas — cualquier cambio de datos causa un redibujado completo mediante notifyDataSetChanged(), lo que crea tirones; (3) sin animación integrada para agregar/eliminar elementos; (4) sin separación de responsabilidades — LayoutManager está integrado, ItemAnimator está ausente.

xml
<!-- item_product.xml — diseño de elemento 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>

Implicaciones prácticas: en listas de hasta 20 elementos, ListView funciona tan rápido como RecyclerView. Con 100+ elementos, la diferencia se vuelve notable: ListView comienza a perder FPS debido a la falta de cálculos diferenciales y ViewHolder forzado. Para listas con actualizaciones frecuentes (chat, feed, registros), ListView no es adecuado — use RecyclerView con Paging 3. En IT Sectr, migramos ListView a RecyclerView siempre que trabajamos en pantallas heredadas con más de 50 elementos.

Configuración de ListView mediante atributos XML

ListView proporciona un conjunto de atributos XML para configuración rápida sin código: android:divider (color/drawable del divisor), android:dividerHeight (grosor), android:scrollbars (barras de desplazamiento), android:fastScrollEnabled (desplazamiento rápido mediante control), android:choiceMode (modo de selección: singleChoice, multipleChoice). El atributo android:entries permite llenar la lista desde un array de recursos (string-array) sin adaptador.

AtributoDescripciónEjemplo de valor
android:dividerColor o drawable del divisor@color/gray_light
android:dividerHeightGrosor del divisor en px/dp1dp
android:entriesArray de cadenas desde recursos@array/countries
android:choiceModeModo de selección de elementossingleChoice
android:fastScrollEnabledDesplazamiento rápidotrue
android:overlapAnchorAnclaje para listas emergentes (API 21+)true

Modo de selección: choiceMode="singleChoice" activa el estilo RadioButton donde el elemento seleccionado se resalta. choiceMode="multipleChoice" — casillas de verificación para múltiples elementos. Los datos de selección están disponibles mediante listView.checkedItemPosition o listView.checkedItemIds. Importante: al usar choiceMode, ListView usa StateListDrawable para el fondo — configure su propio selector si el azul predeterminado no coincide con el diseño.

ListView vs RecyclerView: comparación de características

Elección entre ListView y RecyclerView depende de los requisitos del proyecto. RecyclerView es el estándar moderno, pero ListView puede justificarse para pantallas simples con costos de mantenimiento mínimos para código heredado. Comparación en todos los parámetros clave:

ParámetroListViewRecyclerView
Tamaño de bibliotecaIntegrado en SDK (~60 KB)AndroidX (~300 KB con dependencias)
Versión mínimaAPI 1API 14 (mediante AndroidX)
OrientaciónSolo verticalVertical, horizontal, cuadrícula, escalonado
ViewHolderImplementación manualObligatorio por arquitectura
AnimaciónSolo transiciones de fundidoDefaultItemAnimator (add, remove, move, change)
Actualizaciones detalladasNo (solo notifyDataSetChanged)notifyItemInserted/Removed/Changed
Listener de cliconItemClickListener (integrado)Mediante ViewHolder (no integrado)
RendimientoAdecuado para listas de hasta 50 elementos60 FPS estables para 1000+ elementos

Conclusión: para proyectos nuevos, use RecyclerView. Mantenga ListView solo en código heredado donde la migración sea innecesariamente costosa. Según las pautas de Material Design 3 (2026), las listas de cualquier complejidad deben usar RecyclerView para cumplir con los estándares modernos de rendimiento y accesibilidad.

Preguntas frecuentes

¿ListView está obsoleto o no?

ListView no está marcado como @Deprecated en Android SDK API 35, pero Google no recomienda usarlo en proyectos nuevos (soft-deprecated). El componente sigue siendo funcional en todas las versiones de Android. RecyclerView ha sido el reemplazo oficial desde 2014. Si comienzas un proyecto nuevo — elige RecyclerView. Si mantienes uno existente — ListView continuará funcionando sin cambios.

¿Cómo agregar header/footer a ListView?

ListView admite los métodos addHeaderView(View, Object, boolean) y addFooterView(View, Object, boolean). El encabezado y el pie se agregan a la lista general de elementos pero no participan en el adaptador — siempre se muestran al principio y al final de la lista. Importante: agregue header/footer antes de establecer el adaptador (setAdapter()), de lo contrario no se tendrán en cuenta. Después de agregar un encabezado, los ID de posición de los elementos se desplazan según la cantidad de encabezados.

¿Por qué ListView no se desplaza dentro de ScrollView?

ListView y ScrollView ambos manejan gestos verticales, lo que crea un conflicto: el ScrollView externo intercepta el desplazamiento y ListView no se desplaza. Solución: (1) no anide ListView dentro de ScrollView — use RecyclerView con NestedScrollingChild, (2) reemplace ScrollView con NestedScrollView (API 21+), (3) use ListView con altura fija (android:layout_height="...dp") dentro de ScrollView, pero esto rompe la adaptabilidad.

¿Cómo limpiar ListView y actualizar datos?

La limpieza de datos en ListView depende del tipo de adaptador. Para ArrayAdapter: adapter.clear() y adapter.addAll(newList) seguido de adapter.notifyDataSetChanged(). Para adaptador personalizado: actualice la lista de datos y llame a notifyDataSetChanged(). Nota: listView.invalidateViews() solo redibuja las Views pero no actualiza los datos. Siempre cambie los datos a través del adaptador, no directamente.

¿Cómo cambiar la altura de un elemento de ListView?

La altura de los elementos de ListView se establece en el XML de diseño del elemento. Si el diseño usa layout_height="wrap_content", la altura se ajusta al contenido. Para una altura fija de todos los elementos, use un adaptador personalizado que establezca LayoutParams en getView(): view.layoutParams.height = resources.getDimensionPixelSize(R.dimen.itemHeight). Para alturas variables, use RecyclerView con diferentes tipos de vista.

Resumen

  • ListView es un componente básico del SDK de Android para listas verticales, disponible desde API 1.
  • ArrayAdapter es el adaptador más simple para una lista de cadenas; para diseños personalizados, se necesita un getView() sobrescrito.
  • ViewHolder en ListView se implementa manualmente mediante convertView y view.tag — un requisito de rendimiento obligatorio.
  • ListView admite choiceMode (single/multiple), header/footer, fastScroll y android:entries sin adaptador.
  • Limitaciones de ListView: solo orientación vertical, sin animación, redibujado completo ante cualquier cambio.
  • ListView no está marcado como obsoleto, pero Google recomienda RecyclerView para todos los proyectos nuevos.
  • Para listas de hasta 50 elementos, ListView es suficiente; para cualquier cosa más compleja, use RecyclerView.

Desarrollaremos una aplicación móvil llave en mano

IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.

Discutir el proyecto

Lea también