Saltar al contenido principal

Layouts en Flutter

Aprende cómo funciona el mecanismo de layout de Flutter y cómo construir el layout de tu app.

Resumen

#

El núcleo del mecanismo de layout de Flutter son los Widgets. En Flutter, casi todo es un Widget; incluso los modelos de layout son Widgets. Las imágenes, iconos y texto que ves en una app de Flutter son todos Widgets. Pero las cosas que no ves también son Widgets, como las filas, columnas y cuadrículas que organizan, restringen y alinean los Widgets visibles. Creas un layout componiendo Widgets para construir Widgets más complejos.

Ejemplo conceptual

#

En el siguiente ejemplo, la primera captura de pantalla muestra tres iconos con etiquetas y la segunda captura de pantalla incluye el layout visual para filas y columnas. En la segunda captura de pantalla, debugPaintSizeEnabled está configurado en true para que puedas ver el layout visual.

Layout de muestra
Layout de muestra con depuración visual

Aquí tienes un diagrama del árbol de Widgets para el ejemplo anterior:

Árbol de nodos

La mayor parte de esto debería verse como esperarías, pero podrías estar preguntándote acerca de los contenedores (mostrados en rosa). Container es una clase de Widget que te permite personalizar su Widget hijo. Usa un Container cuando quieras añadir padding, márgenes, bordes o color de fondo, por nombrar algunas de sus capacidades.

Cada Widget Text se coloca en un Container para añadir márgenes. Todo el Row también se coloca en un Container para añadir padding alrededor de la fila.

El resto de la UI se controla mediante propiedades. Establece el color de un Icon usando su propiedad color. Usa la propiedad Text.style para configurar la fuente, su color, grosor, etc. Las columnas y filas tienen propiedades que te permiten especificar cómo se alinean sus hijos vertical u horizontalmente, y cuánto espacio deben ocupar los hijos.

Diseñar un Widget

#

¿Cómo diseñas un solo Widget en Flutter? Esta sección te muestra cómo crear y mostrar un Widget simple. También muestra todo el código para una app simple de Hello World.

En Flutter, solo se necesitan unos pocos pasos para colocar texto, un icono o una imagen en la pantalla.

1. Selecciona un Widget de layout

#

Elige entre una variedad de Widgets de layout según cómo quieras alinear o restringir un Widget visible, ya que estas características se transmiten típicamente al Widget contenido.

Por ejemplo, podrías usar el Widget de layout Center para centrar un Widget visible horizontal y verticalmente:

dart
Center(
  // Content to be centered here.
)

2. Crea un Widget visible

#

Elige un Widget visible para que tu app contenga elementos visibles, como texto, imágenes o iconos.

Por ejemplo, podrías usar el Widget Text para mostrar algo de texto:

dart
Text('Hello World')

3. Añade el Widget visible al Widget de layout

#

Todos los Widgets de layout tienen uno de los siguientes:

  • Una propiedad child si aceptan un solo hijo—por ejemplo, Center o Container
  • Una propiedad children si aceptan una lista de Widgets—por ejemplo, Row, Column, ListView o Stack.

Añade el Widget Text al Widget Center:

dart
const Center(
  child: Text('Hello World'),
),

4. Añade el Widget de layout a la página

#

Una app de Flutter es en sí misma un Widget, y la mayoría de los Widgets tienen un método build(). Instanciar y devolver un Widget en el método build() de la app muestra el Widget.

Para una app general, puedes añadir el Widget Container al método build() de la app:

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

  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: const BoxDecoration(color: Colors.white),
      child: const Center(
        child: Text(
          'Hello World',
          textDirection: TextDirection.ltr,
          style: TextStyle(fontSize: 32, color: Colors.black87),
        ),
      ),
    );
  }
}

Por defecto, una app general no incluye una AppBar, título o color de fondo. Si quieres estas características en una app general, tienes que construirlas tú mismo. Esta app cambia el color de fondo a blanco y el texto a gris oscuro para imitar una app de Material.

Para una app de Material, puedes usar un Widget Scaffold; proporciona un banner por defecto, color de fondo, y tiene API para añadir drawers, snack bars y bottom sheets. Luego puedes añadir el Widget Center directamente a la propiedad body para la página principal.

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

  @override
  Widget build(BuildContext context) {
    const String appTitle = 'Flutter layout demo';
    return MaterialApp(
      title: appTitle,
      home: Scaffold(
        appBar: AppBar(title: const Text(appTitle)),
        body: const Center(
          child: Text('Hello World'),
        ),
      ),
    );
  }
}

Para crear una app de Cupertino, usa los Widgets CupertinoApp y CupertinoPageScaffold.

A diferencia de Material, no proporciona un banner ni color de fondo por defecto. Necesitas configurarlos tú mismo.

  • Para configurar los colores por defecto, pasa un CupertinoThemeData configurado a la propiedad theme de tu app.

  • Para añadir una barra de navegación al estilo de iOS en la parte superior de tu app, añade un Widget CupertinoNavigationBar a la propiedad navigationBar de tu scaffold. Puedes usar los colores que proporciona CupertinoColors para configurar tus Widgets para que coincidan con el diseño de iOS.

  • Para diseñar el body de tu app, establece la propiedad child de tu scaffold con el Widget deseado como su valor, como Center o Column.

Para aprender qué otros componentes de UI puedes añadir, echa un vistazo a la librería de Cupertino.

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

  @override
  Widget build(BuildContext context) {
    return const CupertinoApp(
      title: 'Flutter layout demo',
      theme: CupertinoThemeData(
        brightness: Brightness.light,
        primaryColor: CupertinoColors.systemBlue,
      ),
      home: CupertinoPageScaffold(
        navigationBar: CupertinoNavigationBar(
          backgroundColor: CupertinoColors.systemGrey,
          middle: Text('Flutter layout demo'),
        ),
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [Text('Hello World')],
          ),
        ),
      ),
    );
  }
}

5. Ejecuta tu app

#

Después de haber añadido tus Widgets, ejecuta tu app. Cuando ejecutes la app, deberías ver Hello World.

Código fuente de la app:

Captura de pantalla de la app mostrando Hello World

Diseñar múltiples Widgets vertical y horizontalmente

#

Uno de los patrones de layout más comunes es organizar Widgets vertical u horizontalmente. Puedes usar un Widget Row para organizar Widgets horizontalmente, y un Widget Column para organizar Widgets verticalmente.

Para crear una fila o columna en Flutter, añades una lista de Widgets hijos a un Widget Row o Column. A su vez, cada hijo puede ser en sí mismo una fila o columna, y así sucesivamente. El siguiente ejemplo muestra cómo es posible anidar filas o columnas dentro de filas o columnas.

Este layout está organizado como un Row. La fila contiene dos hijos: una columna a la izquierda y una imagen a la derecha:

Captura de pantalla con acotaciones que muestran la fila que contiene dos hijos

El árbol de Widgets de la columna izquierda anida filas y columnas.

Diagrama que muestra una columna izquierda desglosada en sus subfilas y subcolumnas

Implementarás parte del código de layout de Pavlova en Anidar filas y columnas.

Alinear Widgets

#

Controlas cómo una fila o columna alinea a sus hijos mediante las propiedades mainAxisAlignment y crossAxisAlignment. Para una fila, el eje principal se ejecuta horizontalmente y el eje cruzado se ejecuta verticalmente. Para una columna, el eje principal se ejecuta verticalmente y el eje cruzado se ejecuta horizontalmente.

Diagrama que muestra el eje principal y el eje cruzado para una fila
Diagrama que muestra el eje principal y el eje cruzado para una columna

Los enums MainAxisAlignment y CrossAxisAlignment ofrecen una variedad de constantes para controlar la alineación.

En el siguiente ejemplo, cada una de las 3 imágenes tiene 100 píxeles de ancho. La caja de renderizado (en este caso, la pantalla entera) tiene más de 300 píxeles de ancho, por lo que configurar la alineación del eje principal en spaceEvenly divide el espacio horizontal libre equitativamente entre, antes y después de cada imagen.

dart
Row(
  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  children: [
    Image.asset('images/pic1.jpg'),
    Image.asset('images/pic2.jpg'),
    Image.asset('images/pic3.jpg'),
  ],
);
Fila con 3 imágenes espaciadas uniformemente

App source: row_column

Las columnas funcionan de la misma manera que las filas. El siguiente ejemplo muestra una columna de 3 imágenes, cada una de 100 píxeles de alto. La altura de la caja de renderizado (en este caso, la pantalla entera) es de más de 300 píxeles, por lo que configurar la alineación del eje principal en spaceEvenly divide el espacio vertical libre equitativamente entre, arriba y debajo de cada imagen.

dart
Column(
  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  children: [
    Image.asset('images/pic1.jpg'),
    Image.asset('images/pic2.jpg'),
    Image.asset('images/pic3.jpg'),
  ],
);
Columna que muestra 3 imágenes espaciadas uniformemente

App source: row_column

Ajustar el tamaño de los Widgets

#

Cuando un layout es demasiado grande para adaptarse a un dispositivo, aparece un patrón de rayas amarillas y negras a lo largo del borde afectado. Aquí hay un ejemplo de una fila que es demasiado ancha:

Fila excesivamente ancha

Los Widgets se pueden dimensionar para caber dentro de una fila o columna usando el Widget Expanded. Para solucionar el ejemplo anterior donde la fila de imágenes es demasiado ancha para su caja de renderizado, envuelve cada imagen con un Widget Expanded.

dart
Row(
  crossAxisAlignment: CrossAxisAlignment.center,
  children: [
    Expanded(child: Image.asset('images/pic1.jpg')),
    Expanded(child: Image.asset('images/pic2.jpg')),
    Expanded(child: Image.asset('images/pic3.jpg')),
  ],
);
Fila de 3 imágenes que son demasiado anchas, pero cada una está restringida para ocupar solo 1/3 del espacio

App source: sizing

Tal vez quieras que un Widget ocupe el doble de espacio que sus hermanos. Para esto, usa la propiedad flex del Widget Expanded, un entero que determina el factor flex para un Widget. El factor flex por defecto es 1. El siguiente código establece el factor flex de la imagen central en 2:

dart
Row(
  crossAxisAlignment: CrossAxisAlignment.center,
  children: [
    Expanded(child: Image.asset('images/pic1.jpg')),
    Expanded(flex: 2, child: Image.asset('images/pic2.jpg')),
    Expanded(child: Image.asset('images/pic3.jpg')),
  ],
);
Fila de 3 imágenes con la imagen central el doble de ancha que las demás

App source: sizing

Empaquetar Widgets

#

Por defecto, una fila o columna ocupa el mayor espacio posible a lo largo de su eje principal, pero si quieres empaquetar a los hijos estrechamente juntos, establece su mainAxisSize en MainAxisSize.min. El siguiente ejemplo usa esta propiedad para empaquetar los iconos de estrellas juntos.

dart
Row(
  mainAxisSize: MainAxisSize.min,
  children: [
    Icon(Icons.star, color: Colors.green[500]),
    Icon(Icons.star, color: Colors.green[500]),
    Icon(Icons.star, color: Colors.green[500]),
    const Icon(Icons.star, color: Colors.black),
    const Icon(Icons.star, color: Colors.black),
  ],
)
Fila de 5 estrellas, empaquetadas juntas en el centro de la fila

App source: pavlova

Anidar filas y columnas

#

El framework de layout te permite anidar filas y columnas dentro de filas y columnas tan profundamente como lo necesites. Echemos un vistazo al código para la sección delineada del siguiente layout:

Captura de pantalla de la app pavlova, con las filas de puntuaciones e iconos delineadas en rojo

La sección delineada se implementa como dos filas. La fila de puntuaciones contiene cinco estrellas y el número de opiniones. La fila de iconos contiene tres columnas de iconos y texto.

El árbol de Widgets para la fila de puntuaciones:

Árbol de Widgets de la fila de puntuaciones

La variable ratings crea una fila que contiene una fila más pequeña de iconos de 5 estrellas, y texto:

dart
final stars = Row(
  mainAxisSize: MainAxisSize.min,
  children: [
    Icon(Icons.star, color: Colors.green[500]),
    Icon(Icons.star, color: Colors.green[500]),
    Icon(Icons.star, color: Colors.green[500]),
    const Icon(Icons.star, color: Colors.black),
    const Icon(Icons.star, color: Colors.black),
  ],
);

final ratings = Container(
  padding: const EdgeInsets.all(20),
  child: Row(
    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
    children: [
      stars,
      const Text(
        '170 Reviews',
        style: TextStyle(
          color: Colors.black,
          fontWeight: FontWeight.w800,
          fontFamily: 'Roboto',
          letterSpacing: 0.5,
          fontSize: 20,
        ),
      ),
    ],
  ),
);

La fila de iconos, debajo de la fila de puntuaciones, contiene 3 columnas; cada columna contiene un icono y dos líneas de texto, como puedes ver en su árbol de Widgets:

Árbol de Widgets de iconos

La variable iconList define la fila de iconos:

dart
const descTextStyle = TextStyle(
  color: Colors.black,
  fontWeight: FontWeight.w800,
  fontFamily: 'Roboto',
  letterSpacing: 0.5,
  fontSize: 18,
  height: 2,
);

// DefaultTextStyle.merge() allows you to create a default text
// style that is inherited by its child and all subsequent children.
final iconList = DefaultTextStyle.merge(
  style: descTextStyle,
  child: Container(
    padding: const EdgeInsets.all(20),
    child: Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: [
        Column(
          children: [
            Icon(Icons.kitchen, color: Colors.green[500]),
            const Text('PREP:'),
            const Text('25 min'),
          ],
        ),
        Column(
          children: [
            Icon(Icons.timer, color: Colors.green[500]),
            const Text('COOK:'),
            const Text('1 hr'),
          ],
        ),
        Column(
          children: [
            Icon(Icons.restaurant, color: Colors.green[500]),
            const Text('FEEDS:'),
            const Text('4-6'),
          ],
        ),
      ],
    ),
  ),
);

La variable leftColumn contiene las filas de puntuaciones e iconos, así como el título y el texto que describe la Pavlova:

dart
final leftColumn = Container(
  padding: const EdgeInsets.fromLTRB(20, 30, 20, 20),
  child: Column(children: [titleText, subTitle, ratings, iconList]),
);

La columna izquierda se coloca en un SizedBox para restringir su ancho. Finalmente, la UI se construye con toda la fila (que contiene la columna izquierda y la imagen) dentro de un Card.

La imagen de Pavlova es de Pixabay. Puedes incrustar una imagen desde la red usando Image.network() pero, para este ejemplo, la imagen se guarda en un directorio de imágenes en el proyecto, se añade al archivo pubspec y se accede usando Images.asset(). Para obtener más información, consulta Añadir assets e imágenes.

dart
body: Center(
  child: Container(
    margin: const EdgeInsets.fromLTRB(0, 40, 0, 30),
    height: 600,
    child: Card(
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          SizedBox(width: 440, child: leftColumn),
          mainImage,
        ],
      ),
    ),
  ),
),

App source: pavlova


Widgets de layout comunes

#

Flutter tiene una rica librería de Widgets de layout. Aquí tienes algunos de los más utilizados. La intención es ponerte en marcha lo más rápido posible, en lugar de abrumarte con una lista completa. Para obtener información sobre otros Widgets disponibles, consulta el Catálogo de Widgets, o usa el cuadro de búsqueda en la documentación de referencia de la API. Además, las páginas de Widgets en la documentación de la API a menudo hacen sugerencias sobre Widgets similares que podrían adaptarse mejor a tus necesidades.

Los siguientes Widgets se dividen en dos categorías: Widgets estándar de la librería de widgets y Widgets especializados de la librería de Material. Cualquier app puede usar la librería de widgets pero solo las apps de Material pueden usar la librería de Material Components.

Container

Añade padding, márgenes, bordes, color de fondo u otras decoraciones a un Widget.

GridView

Organiza Widgets como una cuadrícula con desplazamiento.

ListView

Organiza Widgets como una lista con desplazamiento.

Stack

Superpone un Widget encima de otro.

Scaffold

Proporciona un framework de layout estructurado con espacios para elementos comunes de apps de Material Design.

AppBar

Crea una barra horizontal que típicamente se muestra en la parte superior de una pantalla.

Card

Organiza información relacionada en una caja con esquinas redondeadas y una sombra paralela.

ListTile

Organiza hasta 3 líneas de texto, e iconos opcionales al principio y al final, en una fila.

CupertinoPageScaffold

Proporciona la estructura básica de layout para una página al estilo de iOS.

CupertinoNavigationBar

Crea una barra de navegación al estilo de iOS en la parte superior de la pantalla.

CupertinoSegmentedControl

Crea un control segmentado para seleccionar.

CupertinoTabBar y CupertinoTabScaffold

Crea la barra de pestañas inferior característica de iOS.

Container

#

Muchos layouts hacen un uso amplio de Containers para separar Widgets usando padding, o para añadir bordes o márgenes. Puedes cambiar el fondo del dispositivo colocando todo el layout en un Container y cambiando su color o imagen de fondo.

Resumen (Container)

#
  • Añadir padding, márgenes, bordes
  • Cambiar el color o la imagen de fondo
  • Contiene un solo Widget hijo, pero ese hijo puede ser un Row, Column, o incluso la raíz de un árbol de Widgets
Diagrama que muestra: margen, borde, padding y contenido

Ejemplos (Container)

#

Este layout consiste en una columna con dos filas, cada una con 2 imágenes. Se usa un Container para cambiar el color de fondo de la columna a un gris más claro.

dart
Widget _buildImageColumn() {
  return Container(
    decoration: const BoxDecoration(color: Colors.black26),
    child: Column(children: [_buildImageRow(1), _buildImageRow(3)]),
  );
}
Captura de pantalla que muestra 2 filas, cada una con 2 imágenes

También se usa un Container para añadir un borde redondeado y márgenes a cada imagen:

dart
Widget _buildDecoratedImage(int imageIndex) => Expanded(
  child: Container(
    decoration: BoxDecoration(
      border: Border.all(width: 10, color: Colors.black38),
      borderRadius: const BorderRadius.all(Radius.circular(8)),
    ),
    margin: const EdgeInsets.all(4),
    child: Image.asset('images/pic$imageIndex.jpg'),
  ),
);

Widget _buildImageRow(int imageIndex) => Row(
  children: [
    _buildDecoratedImage(imageIndex),
    _buildDecoratedImage(imageIndex + 1),
  ],
);

Puedes encontrar más ejemplos de Container en el tutorial.

App source: container


GridView

#

Usa GridView para organizar Widgets como una lista bidimensional. GridView proporciona dos listas prefabricadas, o puedes construir tu propia cuadrícula personalizada. Cuando un GridView detecta que sus contenidos son demasiado largos para adaptarse a la caja de renderizado, se desplaza automáticamente.

Resumen (GridView)

#
  • Organiza Widgets en una cuadrícula
  • Detecta cuándo el contenido de la columna excede la caja de renderizado y proporciona desplazamiento automáticamente
  • Build your own custom grid, or use one of the provided grids:
    • GridView.count te permite especificar el número de columnas
    • GridView.extent te permite especificar el ancho máximo en píxeles de un tile

Ejemplos (GridView)

#
Una cuadrícula de 3 columnas con fotos

Usa GridView.extent para crear una cuadrícula con tiles de un máximo de 150 píxeles de ancho.

App source: grid_and_list

Una cuadrícula de 2 columnas con pies de página

Usa GridView.count para crear una cuadrícula de 2 tiles de ancho en modo vertical, y 3 tiles de ancho en modo horizontal. Los títulos se crean configurando la propiedad footer para cada GridTile.

Dart code: grid_list_demo.dart

dart
Widget _buildGrid() => GridView.extent(
  maxCrossAxisExtent: 150,
  padding: const EdgeInsets.all(4),
  mainAxisSpacing: 4,
  crossAxisSpacing: 4,
  children: _buildGridTileList(30),
);

// The images are saved with names pic0.jpg, pic1.jpg...pic29.jpg.
// The List.generate() constructor allows an easy way to create
// a list when objects have a predictable naming pattern.
List<Widget> _buildGridTileList(int count) =>
    List.generate(count, (i) => Image.asset('images/pic$i.jpg'));

ListView

#

ListView, un Widget similar a una columna, proporciona automáticamente desplazamiento cuando su contenido es demasiado largo para su caja de renderizado.

Resumen (ListView)

#
  • Un Column especializado para organizar una lista de cajas
  • Se puede organizar horizontal o verticalmente
  • Detecta cuándo su contenido no cabe y proporciona desplazamiento
  • Menos configurable que Column, pero más fácil de usar y admite desplazamiento

Ejemplos (ListView)

#
ListView que contiene cines y restaurantes

Usa ListView para mostrar una lista de negocios usando ListTiles. Un Divider separa los cines de los restaurantes.

App source: grid_and_list

ListView que contiene tonos de azul

Usa ListView para mostrar los Colors de la paleta de Material 2 Design para una familia de colores en particular.

Dart code: colors_demo.dart

dart
Widget _buildList() {
  return ListView(
    children: [
      _tile('CineArts at the Empire', '85 W Portal Ave', Icons.theaters),
      _tile('The Castro Theater', '429 Castro St', Icons.theaters),
      _tile('Alamo Drafthouse Cinema', '2550 Mission St', Icons.theaters),
      _tile('Roxie Theater', '3117 16th St', Icons.theaters),
      _tile(
        'United Artists Stonestown Twin',
        '501 Buckingham Way',
        Icons.theaters,
      ),
      _tile('AMC Metreon 16', '135 4th St #3000', Icons.theaters),
      const Divider(),
      _tile('K\'s Kitchen', '757 Monterey Blvd', Icons.restaurant),
      _tile('Emmy\'s Restaurant', '1923 Ocean Ave', Icons.restaurant),
      _tile('Chaiya Thai Restaurant', '272 Claremont Blvd', Icons.restaurant),
      _tile('La Ciccia', '291 30th St', Icons.restaurant),
    ],
  );
}

ListTile _tile(String title, String subtitle, IconData icon) {
  return ListTile(
    title: Text(
      title,
      style: const TextStyle(fontWeight: FontWeight.w500, fontSize: 20),
    ),
    subtitle: Text(subtitle),
    leading: Icon(icon, color: Colors.blue[500]),
  );
}

Stack

#

Usa Stack para organizar Widgets encima de un Widget base—a menudo una imagen. Los Widgets pueden superponerse completa o parcialmente al Widget base.

Resumen (Stack)

#
  • Úsalo para Widgets que se superponen a otro Widget
  • El primer Widget en la lista de hijos es el Widget base; los hijos posteriores se superponen encima de ese Widget base
  • El contenido de un Stack no se puede desplazar
  • Puedes elegir recortar los hijos que excedan la caja de renderizado

Ejemplos (Stack)

#
Imagen de avatar circular con una etiqueta

Usa Stack para superponer un Container (que muestra su Text en un fondo negro translúcido) encima de un CircleAvatar. El Stack desplaza el texto usando la propiedad alignment y Alignments.

App source: card_and_stack

Una imagen con un icono superpuesto encima

Usa Stack para superponer un icono encima de una imagen.

Dart code: bottom_navigation_demo.dart

dart
Widget _buildStack() {
  return Stack(
    alignment: const Alignment(0.6, 0.6),
    children: [
      const CircleAvatar(
        backgroundImage: AssetImage('images/pic.jpg'),
        radius: 100,
      ),
      Container(
        decoration: const BoxDecoration(color: Colors.black45),
        child: const Text(
          'Mia B',
          style: TextStyle(
            fontSize: 20,
            fontWeight: FontWeight.bold,
            color: Colors.white,
          ),
        ),
      ),
    ],
  );
}

Card

#

Una Card, de la librería de Material, contiene fragmentos relacionados de información y se puede componer de casi cualquier Widget, pero a menudo se usa con ListTile. Card tiene un solo hijo, pero su hijo puede ser una columna, fila, lista, cuadrícula u otro Widget que admita múltiples hijos. Por defecto, una Card reduce su tamaño a 0 por 0 píxeles. Puedes usar SizedBox para restringir el tamaño de una Card.

En Flutter, una Card presenta esquinas ligeramente redondeadas y una sombra paralela, dándole un efecto 3D. Cambiar la propiedad elevation de una Card te permite controlar el efecto de sombra paralela. Establecer la elevación en 24, por ejemplo, eleva visualmente la Card más lejos de la superficie y hace que la sombra se disperse más. Para obtener una lista de valores de elevación admitidos, consulta Elevación en las directrices de Material. Especificar un valor no admitido deshabilita la sombra paralela por completo.

Resumen (Card)

#
  • Implementa una Card de Material
  • Se usa para presentar fragmentos de información relacionada
  • Acepta un solo hijo, pero ese hijo puede ser un Row, Column u otro Widget que contenga una lista de hijos
  • Se muestra con esquinas redondeadas y una sombra paralela
  • El contenido de una Card no se puede desplazar
  • De la librería de Material

Ejemplos (Card)

#
Card que contiene 3 ListTiles

Una Card que contiene 3 ListTiles y dimensionada envolviéndola con un SizedBox. Un Divider separa el primer y segundo ListTiles.

App source: card_and_stack

Card interactiva que contiene una imagen y múltiples formas de texto

Una Card que contiene una imagen y texto.

Dart code: cards_demo.dart

dart
Widget _buildCard() {
  return SizedBox(
    height: 210,
    child: Card(
      child: Column(
        children: [
          ListTile(
            title: const Text(
              '1625 Main Street',
              style: TextStyle(fontWeight: FontWeight.w500),
            ),
            subtitle: const Text('My City, CA 99984'),
            leading: Icon(Icons.restaurant_menu, color: Colors.blue[500]),
          ),
          const Divider(),
          ListTile(
            title: const Text(
              '(408) 555-1212',
              style: TextStyle(fontWeight: FontWeight.w500),
            ),
            leading: Icon(Icons.contact_phone, color: Colors.blue[500]),
          ),
          ListTile(
            title: const Text('costa@example.com'),
            leading: Icon(Icons.contact_mail, color: Colors.blue[500]),
          ),
        ],
      ),
    ),
  );
}

ListTile

#

Usa ListTile, un Widget de fila especializado de la librería de Material, para una forma fácil de crear una fila que contenga hasta 3 líneas de texto e iconos opcionales al principio y al final. ListTile se usa más comúnmente en Card o ListView, pero se puede usar en otros lugares.

Resumen (ListTile)

#
  • Una fila especializada que contiene hasta 3 líneas de texto e iconos opcionales
  • Menos configurable que Row, pero más fácil de usar
  • De la librería de Material

Ejemplos (ListTile)

#
Card que contiene 3 ListTiles

Una Card que contiene 3 ListTiles.

App source: card_and_stack

4 ListTiles, cada uno con un avatar principal

Usa ListTile con Widgets principales.

Dart code: list_demo.dart


Restricciones

#

Para entender completamente el sistema de layout de Flutter, necesitas aprender cómo Flutter posiciona y dimensiona los componentes en un layout. Para obtener más información, consulta Entender las restricciones.

Videos

#

Los siguientes videos, parte de la serie Flutter en Focus, explican los Widgets Stateless y Stateful.

Ver en YouTube en una nueva pestaña: "Cómo crear Widgets Stateless"

Ver en YouTube en una nueva pestaña: "Cómo y cuándo se usan mejor los Widgets Stateful"

Lista de reproducción de Flutter en Focus


Cada episodio de la serie Widget of the Week se centra en un Widget. Varios de ellos incluyen Widgets de layout.

Ver en YouTube en una nueva pestaña: "Presentamos Widget of the Week"

Lista de reproducción de Flutter Widget of the Week

Otros recursos

#

Los siguientes recursos te pueden ayudar al escribir código de layout.

Tutorial de layout

Aprende a construir un layout.

Catálogo de Widgets

Describe muchos de los Widgets disponibles en Flutter.

Análogos de HTML/CSS en Flutter

Para aquellos familiarizados con la programación web, esta página mapea la funcionalidad de HTML/CSS a las características de Flutter.

Documentación de referencia de la API

Documentación de referencia para todas las librerías de Flutter.

Añadir assets e imágenes

Explica cómo añadir imágenes y otros assets al paquete de tu app.

De Cero a Uno con Flutter

La experiencia de una persona al escribir su primera app de Flutter.