Tutorial de layout
Esta es una guía para construir layouts en Flutter. Construirás el layout para la siguiente aplicación:
Esta guía da un paso atrás para explicar el enfoque de Flutter sobre el layout y muestra cómo colocar un único widget en la pantalla. Después de una discusión sobre cómo colocar los widgets horizontalmente y verticalmente, se tratan algunos de los widgets de layout más comunes.
Si deseas una visión general del mecanismo de layout, comienza con el enfoque de Flutter sobre el layout.
Paso 0: Crear el código base de la aplicación
Asegúrate de haber configurado tu entorno y luego haz lo siguiente:
- Crea una aplicación básica Flutter “Hello World”.
-
Cambia el título de la barra de aplicaciones y el título de la aplicación como sigue:
{codelabs/startup_namer/step1_base → layout/base}/lib/main.dart@@ -6,10 +6,10 @@66@override77Widget build(BuildContext context) {88return MaterialApp(9- title: 'WelcometoFlutter',9+ title: 'Flutter layout demo',1010home: Scaffold(1111appBar: AppBar(12- title: Text('WelcometoFlutter'),12+ title: Text('Flutter layout demo'),1313),1414body: Center(1515child: Text('Hello World'),
Paso 1: Diagrama del layout
El primer paso es desglosar el layout en sus elementos básicos:
- Identificar las filas y columnas.
- ¿El layout incluye una cuadrícula?
- ¿Hay elementos que se superponen?
- ¿Necesita pestañas la interfaz de usuario?
- Observe las áreas que requieren alineación, padding o bordes.
Primero, identifica los elementos más grandes. En este ejemplo, cuatro elementos están dispuestos en una columna: una imagen, dos filas y un bloque de texto.
A continuación, diagrama cada fila. La primera fila, llamada sección Título, tiene 3 hijos: una columna de texto, un icono de estrella y un número. Su primer hijo, la columna, contiene 2 líneas de texto. Esa primera columna ocupa mucho espacio, por lo que debe estar envuelta en un widget Expanded.
La segunda fila, llamada sección Botón, también tiene 3 hijos: cada hijo es una columna que contiene un icono y un texto.
Una vez que se ha diagramado el layout, lo más fácil es adoptar un enfoque ascendente para implementarlo. Para minimizar la confusión visual del código de layout profundamente anidado, coloca parte de la implementación en variables y funciones.
Paso 2: Implementar la fila de título
Primero, construirás la columna izquierda en la sección de título. Agrega el siguiente código en la parte superior del método build() de la clase MyApp:
Widget titleSection = Container(
padding: const EdgeInsets.all(32),
child: Row(
children: [
Expanded(
/*1*/
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
/*2*/
Container(
padding: const EdgeInsets.only(bottom: 8),
child: Text(
'Oeschinen Lake Campground',
style: TextStyle(
fontWeight: FontWeight.bold,
),
),
),
Text(
'Kandersteg, Switzerland',
style: TextStyle(
color: Colors.grey[500],
),
),
],
),
),
/*3*/
Icon(
Icons.star,
color: Colors.red[500],
),
Text('41'),
],
),
);- Al colocar una columna dentro de un widget Expanded, se estira la columna
para utilizar todo el espacio libre que queda en la fila. Al establecer
la propiedad
crossAxisAlignmentaCrossAxisAlignment.startse posiciona la columna al principio de la fila. - Poner la primera fila de texto dentro de un Container te permite añadir padding. El segundo hijo en la Columna, también texto, se visualiza como gris.
- Los dos últimos elementos de la fila del título son un icono de estrella, pintado de rojo, y el texto “41”. Toda la fila está en un Container y con padding a lo largo de cada borde por 32 píxeles.
Añade la sección de título al cuerpo de la aplicación de esta manera:
|
@@ -8,11 +46,13 @@
|
|
|
8
46
|
return MaterialApp(
|
|
9
47
|
title: 'Flutter layout demo',
|
|
10
48
|
home: Scaffold(
|
|
11
49
|
appBar: AppBar(
|
|
12
50
|
title: Text('Flutter layout demo'),
|
|
13
51
|
),
|
|
14
|
-
body:
|
|
15
|
-
|
|
52
|
+
body: Column(
|
|
53
|
+
children: [
|
|
54
|
+
titleSection,
|
|
55
|
+
],
|
|
16
56
|
),
|
|
17
57
|
),
|
|
18
58
|
);
|
Paso 3: Implementar la fila de botones
La sección de botones contiene 3 columnas que utilizan la misma disposición: un icono sobre una línea de texto. Las columnas de esta fila están espaciadas uniformemente, y el texto y los iconos están pintados con el color primario.
Como el código para construir cada columna es casi idéntico, crea un método
de ayuda privado llamado buildButtonColumn(), que toma un color, un Icono
y Texto, y devuelve una columna con sus widgets pintados con el color dado.
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// ···
}
Column _buildButtonColumn(Color color, IconData icon, String label) {
return Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(icon, color: color),
Container(
margin: const EdgeInsets.only(top: 8),
child: Text(
label,
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w400,
color: color,
),
),
),
],
);
}
}La función añade el icono directamente a la columna. El texto se encuentra dentro de un Container con un margen superior, separando el texto del icono.
Construye la fila que contiene estas columnas llamando a la función y pasando el color,
Icon, y el texto específico de esa columna. Alinea las columnas a lo largo del eje principal utilizando MainAxisAlignment.spaceEvenly para organizar el espacio libre uniformemente antes, entre y después de cada columna. Agrega el siguiente código justo debajo de la declaración titleSection dentro del método build():
Color color = Theme.of(context).primaryColor;
Widget buttonSection = Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
_buildButtonColumn(color, Icons.call, 'CALL'),
_buildButtonColumn(color, Icons.near_me, 'ROUTE'),
_buildButtonColumn(color, Icons.share, 'SHARE'),
],
),
);Añade la sección de botones al body:
|
@@ -46,3 +59,3 @@
|
|
|
46
59
|
return MaterialApp(
|
|
47
60
|
title: 'Flutter layout demo',
|
|
48
61
|
home: Scaffold(
|
|
@@ -52,8 +65,9 @@
|
|
|
52
65
|
body: Column(
|
|
53
66
|
children: [
|
|
54
67
|
titleSection,
|
|
68
|
+
buttonSection,
|
|
55
69
|
],
|
|
56
70
|
),
|
|
57
71
|
),
|
|
58
72
|
);
|
|
59
73
|
}
|
Paso 4: Implementar la sección de texto
Define la sección de texto como una variable. Pon el texto en un Container y
agrega padding a lo largo de cada borde. Añade el siguiente código justo
debajo de la declaración buttonSection:
Widget textSection = Container(
padding: const EdgeInsets.all(32),
child: Text(
'Lake Oeschinen lies at the foot of the Blüemlisalp in the Bernese '
'Alps. Situated 1,578 meters above sea level, it is one of the '
'larger Alpine Lakes. A gondola ride from Kandersteg, followed by a '
'half-hour walk through pastures and pine forest, leads you to the '
'lake, which warms to 20 degrees Celsius in the summer. Activities '
'enjoyed here include rowing, and riding the summer toboggan run.',
softWrap: true,
),
);Al establecer softwrap a true, las líneas de texto rellenarán el ancho de
la columna antes de ajustarla al límite de una palabra.
Añade la sección de texto al body:
|
@@ -59,3 +72,3 @@
|
|
|
59
72
|
return MaterialApp(
|
|
60
73
|
title: 'Flutter layout demo',
|
|
61
74
|
home: Scaffold(
|
|
@@ -66,6 +79,7 @@
|
|
|
66
79
|
children: [
|
|
67
80
|
titleSection,
|
|
68
81
|
buttonSection,
|
|
82
|
+
textSection,
|
|
69
83
|
],
|
|
70
84
|
),
|
|
71
85
|
),
|
Paso 5: Implementar la sección de imagen
Tres de los cuatro elementos de la columna están ahora completos, dejando sólo la imagen. Añade el archivo de imagen al ejemplo:
- Crea un directorio
imagesen la parte superior del proyecto. -
Añade
lake.jpg. -
Actualice el archivo
pubspec.yamlpara incluir una etiquetaassets. Esto hace que la imagen esté disponible para tu código.{step4 → step5}/pubspec.yaml@@ -17,3 +17,5 @@1717flutter:1818uses-material-design: true19+ assets:20+ - images/lake.jpg
Ahora puedes referenciar la imagen de tu código:
|
@@ -77,6 +77,12 @@
|
|
|
77
77
|
),
|
|
78
78
|
body: Column(
|
|
79
79
|
children: [
|
|
80
|
+
Image.asset(
|
|
81
|
+
'images/lake.jpg',
|
|
82
|
+
width: 600,
|
|
83
|
+
height: 240,
|
|
84
|
+
fit: BoxFit.cover,
|
|
85
|
+
),
|
|
80
86
|
titleSection,
|
|
81
87
|
buttonSection,
|
|
82
88
|
textSection,
|
BoxFit.cover le dice al framework que la imagen debe ser lo más pequeña posible pero que debe cubrir toda su caja de render.
Paso 6: El toque final
En este paso final, ordena todos los elementos en un ListView, en lugar de una
Column, porque un ListView soporta el desplazamiento del body de la aplicación
cuando la aplicación se ejecuta en un dispositivo pequeño.
|
@@ -72,13 +77,13 @@
|
|
|
72
77
|
return MaterialApp(
|
|
73
78
|
title: 'Flutter layout demo',
|
|
74
79
|
home: Scaffold(
|
|
75
80
|
appBar: AppBar(
|
|
76
81
|
title: Text('Flutter layout demo'),
|
|
77
82
|
),
|
|
78
|
-
body:
|
|
83
|
+
body: ListView(
|
|
79
84
|
children: [
|
|
80
85
|
Image.asset(
|
|
81
86
|
'images/lake.jpg',
|
|
82
87
|
width: 600,
|
|
83
88
|
height: 240,
|
|
84
89
|
fit: BoxFit.cover,
|
Dart code: main.dart
Image: images
Pubspec: pubspec.yaml
¡Eso es todo! Cuando recargas la aplicación en caliente, deberías ver el mismo layout de la aplicación como la de la captura de pantalla en la parte superior de esta página.
Puedes añadir interactividad a este layout siguiendo el enlace Agregando interactividad a tu aplicación Flutter.

