Saltar al contenido principal

Lista con elementos espaciados

Cómo crear una lista con elementos espaciados o expandidos

Tal vez quieras crear una lista donde todos los elementos de la lista estén espaciados uniformemente, de modo que ocupen el espacio visible. Por ejemplo, los cuatro elementos en la siguiente imagen están espaciados uniformemente, con "Item 0" en la parte superior y "Item 3" en la inferior.

Elementos espaciados

Al mismo tiempo, es posible que quieras permitir a los usuarios desplazarse por la lista cuando esta no quepa, tal vez porque el dispositivo es demasiado pequeño, el usuario cambió el tamaño de la ventana o el número de elementos supera el tamaño de la pantalla.

Elementos desplazables

Normalmente, usas Spacer para ajustar el espaciado entre widgets, o Expanded para expandir un widget y llenar el espacio disponible. Sin embargo, estas soluciones no son posibles dentro de widgets desplazables, porque necesitan una restricción de altura finita.

Esta receta demuestra cómo usar LayoutBuilder y ConstrainedBox para espaciar uniformemente los elementos de la lista cuando hay suficiente espacio, y permitir a los usuarios desplazarse cuando no hay suficiente espacio, siguiendo estos pasos:

  1. Añadir un LayoutBuilder con un SingleChildScrollView.
  2. Añadir un ConstrainedBox dentro del SingleChildScrollView.
  3. Crear un Column con elementos espaciados.

1. Añadir un LayoutBuilder con un SingleChildScrollView

#

Comienza creando un LayoutBuilder. Debes proporcionar una función callback builder con dos parámetros:

  1. El BuildContext proporcionado por el LayoutBuilder.
  2. Las BoxConstraints del widget padre.

En esta receta, no usarás el BuildContext, pero necesitarás las BoxConstraints en el siguiente paso.

Dentro de la función builder, devuelve un SingleChildScrollView. Este widget asegura que el widget hijo se pueda desplazar, incluso cuando el contenedor padre es demasiado pequeño.

dart
LayoutBuilder(
  builder: (context, constraints) {
    return SingleChildScrollView(child: Placeholder());
  },
);

2. Añadir un ConstrainedBox dentro del SingleChildScrollView

#

En este paso, añade un ConstrainedBox como hijo del SingleChildScrollView.

El widget ConstrainedBox impone restricciones adicionales a su hijo.

Configura la restricción estableciendo el parámetro minHeight para que sea el maxHeight de las restricciones de LayoutBuilder.

Esto asegura que el widget hijo esté restringido a tener una altura mínima igual al espacio disponible proporcionado por las restricciones de LayoutBuilder, es decir, la altura máxima de BoxConstraints.

dart
LayoutBuilder(
  builder: (context, constraints) {
    return SingleChildScrollView(
      child: ConstrainedBox(
        constraints: BoxConstraints(minHeight: constraints.maxHeight),
        child: Placeholder(),
      ),
    );
  },
);

Sin embargo, no estableces el parámetro maxHeight, porque necesitas permitir que el hijo sea más grande que el tamaño de LayoutBuilder, en caso de que los elementos no quepan en la pantalla.

3. Crear un Column con elementos espaciados

#

Finalmente, añade un Column como hijo del ConstrainedBox.

Para espaciar los elementos uniformemente, establece mainAxisAlignment a MainAxisAlignment.spaceBetween.

dart
LayoutBuilder(
  builder: (context, constraints) {
    return SingleChildScrollView(
      child: ConstrainedBox(
        constraints: BoxConstraints(minHeight: constraints.maxHeight),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            ItemWidget(text: 'Item 1'),
            ItemWidget(text: 'Item 2'),
            ItemWidget(text: 'Item 3'),
          ],
        ),
      ),
    );
  },
);

Alternativamente, puedes usar el widget Spacer para ajustar el espaciado entre los elementos, o el widget Expanded si quieres que un widget ocupe más espacio que otros.

Para eso, tienes que envolver el Column con un widget IntrinsicHeight, el cual obliga al widget Column a dimensionarse a una altura mínima, en lugar de expandirse infinitamente.

dart
LayoutBuilder(
  builder: (context, constraints) {
    return SingleChildScrollView(
      child: ConstrainedBox(
        constraints: BoxConstraints(minHeight: constraints.maxHeight),
        child: IntrinsicHeight(
          child: Column(
            children: [
              ItemWidget(text: 'Item 1'),
              Spacer(),
              ItemWidget(text: 'Item 2'),
              Expanded(child: ItemWidget(text: 'Item 3')),
            ],
          ),
        ),
      ),
    );
  },
);

Ejemplo interactivo

#

Este ejemplo muestra una lista de elementos que están espaciados uniformemente dentro de una columna. La lista se puede desplazar hacia arriba y hacia abajo cuando los elementos no caben en la pantalla. El número de elementos se define por la variable items, cambia este valor para ver qué sucede cuando los elementos no quepan en la pantalla.