Saltar al contenido principal

Layout

Aprende sobre los widgets de layout comunes en Flutter.

Aprende a construir layouts con widgets comunes como Scaffold, AppBar, Column y Row.

Qué lograrás

Estructurar una aplicación con Scaffold y AppBar
Organizar widgets usando Column y Row
Generar widgets dinámicamente a partir de datos
Construir un layout de cuadrícula para el tablero de juego

Pasos

1

Introducción

Dado que Flutter es un kit de herramientas de UI, pasarás mucho tiempo creando layouts con widgets de Flutter.

En esta sección, aprenderás cómo construir layouts con algunos de los widgets de layout más comunes. Esto incluye widgets de alto nivel como Scaffold y AppBar, que distribuyen la estructura de una pantalla, así como widgets de nivel inferior como Column o Row que distribuyen widgets vertical u horizontalmente.

2

Scaffold y AppBar

Las aplicaciones móviles suelen tener una barra en la parte superior llamada "barra de la aplicación" (app bar) que puede mostrar un título, controles de navegación y/o acciones.

Una captura de pantalla de una aplicación simple con una barra en la parte superior que tiene un título y un botón de configuración.

La forma más sencilla de añadir una app bar a tu app es usando dos widgets: Scaffold y AppBar.

Scaffold es un widget de conveniencia que proporciona un diseño de página al estilo Material, facilitando la adición de una app bar, drawer, barra de navegación y más a una página de tu app. AppBar es, por supuesto, la barra de la aplicación.

El código generado por el comando flutter create --empty ya contiene un widget AppBar y un widget Scaffold. El siguiente código lo actualiza para usar un widget de layout adicional: Align. Esto posiciona el título a la izquierda, el cual por defecto estaría centrado. El widget Text contiene el título en sí.

Modifica el Scaffold dentro del método build de tu widget MainApp.

Pasar un enum o propiedad estática directamente (como Alignment.centerLeft) también se puede acortar usando la sintaxis de atajos de punto de Dart, sobre la cual puedes leer más tanto en la documentación oficial de Dart como en el resumen de atajos de Flutter.

dart
class MainApp extends StatelessWidget {
  const MainApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Align(
            alignment: Alignment.centerLeft,
            child: Text('Birdle'),
          ),
        ),
        body: Center(child: Text('Hello World!')),
      ),
    );
  }
}

Un árbol de widgets actualizado

#

Considerar el árbol de widgets de tu app se vuelve más importante a medida que tu app crece. En este punto, hay una "rama" en el árbol de widgets por primera vez, y ahora se ve como la siguiente figura:

Una captura de pantalla que se asemeja al popular juego Wordle.
3

Crear un widget para el layout de la página del juego

Añade el siguiente código para un nuevo widget, llamado GamePage, a tu archivo main.dart. Este widget eventualmente mostrará los elementos de UI necesarios para el juego en sí.

lib/main.dart
dart
class GamePage extends StatelessWidget {
  GamePage({super.key});
  // This object is part of the game.dart file.
  // It manages wordle logic, and is outside the scope of this tutorial.
  final Game _game = Game();

  @override
  Widget build(BuildContext context) {
    // TODO: Replace with screen contents
    return Container();
  }
}

Luego, actualiza tu widget MainApp para crear y mostrar un widget GamePage en lugar de "¡Hola Mundo!".

dart
class MainApp extends StatelessWidget {
  const MainApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Align(
            alignment: Alignment.centerLeft,
            child: Text('Birdle'),
          ),
        ),
        body: Center(child: GamePage()),
      ),
    );
  }
}
4

Organizar widgets con Column y Row

El layout de GamePage contiene la cuadrícula de tiles que muestran los intentos del usuario.

Una captura de pantalla que se asemeja al popular juego Wordle.

Hay varias formas de construir este layout. La más sencilla es con los widgets Column y Row. Cada fila contiene cinco tiles que representan las cinco letras de un intento, con un total de cinco filas. Así que necesitarás una única Column con cinco widgets Row como hijos, donde cada fila contenga cinco hijos.

Para empezar, reemplaza el Container en GamePage.build con un widget Padding con un widget Column como su hijo:

dart
class GamePage extends StatelessWidget {
  GamePage({super.key});
  // This manages game logic, and is out of scope for this lesson.
  final Game _game = Game();

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: Column(
        spacing: 5.0,
        children: [
          // Add children next.
        ],
      ),
    );
  }
}

La propiedad spacing coloca cinco píxeles entre cada elemento en el eje principal.

Dentro de Column.children, para cada elemento en la lista _game.guesses, añade un widget Row como hijo.

dart
class GamePage extends StatelessWidget {
  GamePage({super.key});
  // This manages game logic, and is out of scope for this lesson.
  final Game _game = Game();

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: Column(
        spacing: 5.0,
        children: [
          for (final guess in _game.guesses)
            Row(
              spacing: 5.0,
              children: [
                // We'll add the tiles here later.
              ],
            ),
        ],
      ),
    );
  }
}

El bucle for en la lista de children se denomina collection for element, una sintaxis de Dart que te permite añadir elementos a una colección de forma iterativa cuando se construye en tiempo de ejecución. Este azúcar sintáctico te facilita el trabajo con colecciones de widgets, proporcionando una alternativa declarativa a lo siguiente:

dart
[..._game.guesses.map((guess) => Row(/* ... */))],

En este caso, añade cinco widgets Row a la columna, uno por cada intento en el objeto Game.

Un árbol de widgets actualizado

#

El árbol de widgets para esta app se ha expandido significativamente en esta lección. Ahora se parece más a la siguiente figura (abreviada):

Un diagrama que muestra una estructura en forma de árbol con un nodo para cada widget en la aplicación.

Cuando recargues tu app, deberías ver una cuadrícula de 5x5 de cuadrados blancos.

Una captura de pantalla que se asemeja al popular juego Wordle.
5

Revisión

Qué lograste

Aquí tienes un resumen de lo que construiste y aprendiste en esta lección.
Estructuré tu aplicación con Scaffold y AppBar

Usaste Scaffold para proporcionar un diseño de página al estilo Material y AppBar para añadir una barra de título en la parte superior de tu app. Estos widgets de alto nivel le dan a tu app una estructura estándar y, al mismo tiempo, pulida.

Organicé los widgets usando Column y Row

Column organiza los widgets verticalmente y Row los organiza horizontalmente. Estos son widgets de layout fundamentales que usarás constantemente en Flutter. La propiedad spacing añade espacios consistentes entre los hijos.

Generé widgets dinámicamente a partir de datos

Utilizaste un elemento collection for para construir widgets a partir de una lista. Este enfoque declarativo te permite construir interfaces de usuario que reflejan de forma automática y visualmente tus datos, un patrón central para el desarrollo de Flutter.

Construí la cuadrícula del tablero de juego

Al anidar widgets Row dentro de una Column y usar bucles anidados, creaste una cuadrícula de 5x5 de widgets Tile. ¡Tu app ahora muestra el diseño completo del tablero de juego!

6

Ponte a prueba

Quiz de layout

1 / 2
What is the primary difference between a Column and a Row widget?
  1. Column organiza los hijos verticalmente; Row organiza los hijos horizontalmente.

    ¡Así es!

    Column organiza sus hijos a lo largo del eje vertical, mientras que Row utiliza el eje horizontal.

  2. Column es para contenido con scroll; Row es para contenido estático.

    No exactamente.

    Tanto Column como Row son para diseño/maquetación, no para scroll. Usa ListView o SingleChildScrollView para tener scroll.

  3. Column requiere un Scaffold padre; Row no.

    No exactamente.

    Ninguno de los dos widgets requiere un Scaffold como padre.

  4. Column puede tener hijos ilimitados; Row está limitado a dos.

    No exactamente.

    Ambos widgets pueden tener cualquier número de hijos.

What does the Scaffold widget provide in a Flutter app?
  1. Solo un color de fondo para la página.

    No exactamente.

    Scaffold proporciona mucho más, incluyendo estructura para app bars, drawers y más.

  2. Administración del State automática para la página.

    No exactamente.

    Scaffold no administra el State; usas StatefulWidget o soluciones de State Management para eso.

  3. Una forma de navegar entre diferentes páginas.

    No exactamente.

    La navegación es manejada por el Navigator, no por Scaffold.

  4. Un diseño de página al estilo Material con espacios para barra de aplicación, cuerpo, cajón (drawer) y más.

    ¡Así es!

    Scaffold es un widget de conveniencia que proporciona una estructura de página Material estándar.