Flutter ListView y ScrollPhysics: Una vista detallada

Explorando el Widget ListView y sus propiedades en profundidad.

Rurick M. Poisot
Comunidad Flutter
Published in
6 min readJun 2, 2019

--

Articulo original escrito por Deven Joshi traducido por Rurick Maqueo

Nota: esta es una traducción integra del articulo original, es posible que algunos links enlacen a paginas en ingles y los enunciados que hablen en primera persona hacen referencia a Deven no a mi.

Hace un tiempo escribí un articulo con el uso básico del ListView y GridView (traducción pendiente). Este articulo está enfocado en dar una exploración mas detallada de la Clase ListView y ScrollPhysics junto con modificaciones y optimización del widget en general.

En Flutter una ListView es una lista lineal deslizable de elementos. Podemos usarla para hacer una lista de elementos desplazable o una lista de elementos repetidos.

Explorando los tipos de ListView

Empezaremos con una pequeña mirada a los tipos de ListView y mas adelante a las demás propiedades y fantásticas modificaciones para estas.

Vamos a ver los tipos de ListView que hay:

  1. ListView
  2. ListView.builder
  3. ListView.separated
  4. ListView.custom

Vamos a explorar uno por uno:

ListView

Este es el constructor por defecto de la clase ListView. Una ListView simplemente toma una lista de hijos y la hace desplazable.

Una lista creada con el constructor por defecto

El formato general del código es:

Usualmente esto debe ser usado con un pequeño numero de hijos ya que el ListView también construye los elementos visibles de la lista y una cantidad grande de elementos podria renderizar de manera ineficiente.

ListView.builder()

El constructor builder() construye una lista de elementos repetidos. El constructor toma dos parámetros: un itemCount para el numero de elementos in la lista y un itemBuilder para construir cada elemento de la lista.

Una lista construida usando el constructor builder()

El formato general para el código es:

La lista de elementos es construida perezosamente, significa que solo un numero especifico de elementos es construido y cuando el usuario se desplaza los creados anteriormente son destruidos.

Super Truco: Ya que los elementos son cargados perezosamente y solo el numero necesario de elementos es cargado, realmente no necesitamos un itemCount como un parámetro obligatorio, sin éste la lista se hará infinita.

Un ListView sin el parámetro itemCount

ListView.separated()

En el constructor separated() vamos a generar una lista y especificaremos el separador que estará entre cada elemento.

Un ListView construido usando el constructor separated

En esencia construimos dos listas intercaladas: una es la lista principal y la otra es la lista de separadores.

Nótese que el numero infinito de elementos visto en el constructor anterior no puede ser usado aquí, este constructor obliga a tener un itemCount.

El código para este tipo de lista va así:

Este tipo de listas te permite definir separadores de manera dinámica, tener diferentes tipos de separadores para diferentes tipos de elementos, agregar o remover separadores cuando sea necesario, etc…

Esta implementación puede ser usada para insertar otro tipo de elementos (publicidad por ejemplo) de manera sencilla y sin ninguna modificación a la lista principal.

Ejemplo que muestra publicidad en cada posición divisible por 4

Nota: El tamaño de la lista de separadores es menor en 1 que el tamaño de la lista de elementos ya que el separador no existe después del ultimo elemento.

ListView.custom()

El constructor custom(), como su nombre sugiere, te permite construir un ListView con una funcionalidad personalizada en como serán construidos los hijos de la lista. El parámetro principal requiere para esto un SliverChildDelegate que construye los elementos.

Los tipos de SliverChildDelegate son:

  1. SliverChildListDelegate
  2. SliverChildBuilderDelegate

SliverChildListDelegate acepta directamente una lista de hijos mientras que SliverChildBuilderDelegate acepta un IndexedWidgetBuilder (la función constructor que usamos).

Puedes usar o subclasear (heredar de la clase) estos para construir tus propios delegados.

ListView.builder es esencialmente un ListView.custom con un SliverChildBuilderDelegate.

El constructor ListView.default se comporta como un ListView.custom con un SliverChildListDelegate.

Ahora que acabamos con los tipo de ListViews vamos a ver las ScrollPhysics.

Explorando ScrollPhysics

Para controlar la manera de hacer scroll configuramos el parámetro physics en el constructor del ListView. Los diferentes tipos son:

NeverScrollablePhysics

NeverScrollablePhysics renderiza la lista de manera no deslizable. Usa esto para des habilitar completamente el desplazamiento del ListView.

BouncingScrollPhysics

BouncingScrollPhysics hace rebotar la lista cuando termina. Es una efecto similar al usado en iOS.

ClampingScrollPhysics

Esta es el ScrollingPhysics usado en android. La lista se detiene al final y muestra un efecto que lo indica.

FixedExtentScrollPhysics

Esta física es un poco diferente a las demás vistas en el sentido de que solo funciona con FixedExtendedScrollControllers y listas que los usen. Por ejemplo, tomaremos una ListWheelScrollView que crea una lista en forma de rueda.

FixedExtentScrollPhysics solo desliza hacia los elementos en lugar de los espacios entre ellos.

El código para este ejemplo es extremadamente simple:

Unas pocas cosas mas por saber

¿Cómo mantener vivos los elementos que son destruidos en una lista?

Flutter nos da un widget llamado KeepAlive() el cual mantiene con vida lo que en otra circunstancia seria destruido. En una lista, los elementos son encapsulados por defecto en un AutomaticKeepAlive widget.

AutomaticKeepAlives puede ser des habilitado configurando el parámetro addAutomaticKeepAlives a false. Esto es útil en casos donde los elementos no necesitan mantenerse con vida o para una implementación personalizada de KeepAlive.

¿Por qué mi ListView tiene un espacio entre la lista y los widgets exteriores

Por defecto, una ListView tiene un padding entre esta y los widgets exteriores, para removerlo solo configura el padding a EdgeInsets.all(0.0).

¡Eso es todo por este articulo! Espero lo hayan disfrutado y que dejen un par de aplausos si es así. Siganme para mas artículos de Flutter y comenten cualquier duda o sugerencia sobre el articulo.

--

--

Rurick M. Poisot
Comunidad Flutter

Fullstack Web & Flutter Mobile Dev, Lover of tech with a geek heart 💙 👨‍💻 🕹