Diferencia entre revisiones de «Flutter Widget Diseño de pantallas»
Ir a la navegación
Ir a la búsqueda
Imagen obtenida de este sito web
En color rojo tenemos el padding y en color verde tenemos el margin
| Línea 328: | Línea 328: | ||
| − | * Normalmente son usados cuando queramos centrar o alinear un único widget. | + | * Normalmente son usados cuando queramos centrar o alinear un único widget. La diferencia entre Align y Center es que con Align podemos establecer donde situar al Widget dentro de su contenedor (arriba-abajo, izquierda-derecha) mientras que con Center siempre lo va a centrar. |
| − | [[Imagen: | + | [[Imagen:Flutter_dart_container_2.JPG|300px|center]] |
:<syntaxhighlight lang="java" enclose="div" highlight=""> | :<syntaxhighlight lang="java" enclose="div" highlight=""> | ||
| + | import 'package:flutter/material.dart'; | ||
| + | |||
| + | class AlignCenterPage extends StatelessWidget { | ||
| + | |||
| + | @override | ||
| + | Widget build(BuildContext context) { | ||
| + | return Scaffold( | ||
| + | appBar: AppBar( | ||
| + | title: Text('Ejemplo de Align y Center'), | ||
| + | ), | ||
| + | body: _conjuntoContenedores() | ||
| + | ); | ||
| + | } | ||
| + | |||
| + | Widget _conjuntoContenedores(){ | ||
| + | return Column( | ||
| + | children: [ | ||
| + | Center( | ||
| + | child: Container( | ||
| + | height: 150.0, | ||
| + | width: 150.0, | ||
| + | color: Colors.yellow, | ||
| + | child: Center(child: Icon(Icons.access_alarm,size: 40.0,)), | ||
| + | ), | ||
| + | ), | ||
| + | Align( | ||
| + | alignment: Alignment.centerRight, // Es igual que sea top o botton. Sólo hace uso del right al usar Column | ||
| + | child: Container( | ||
| + | height: 150.0, | ||
| + | width: 150.0, | ||
| + | color: Colors.red, | ||
| + | child: Align( | ||
| + | alignment: Alignment.bottomLeft, // Sitúa al icono abajo a la izquierda con respecto a su contenedor | ||
| + | child: Icon(Icons.ac_unit,size: 40.0,), | ||
| + | ), | ||
| + | ), | ||
| + | ), | ||
| + | Expanded( | ||
| + | child: Container( // Creo un container que ocupe todo el espacio restante | ||
| + | color: Colors.brown, | ||
| + | child: Align( | ||
| + | alignment: Alignment.bottomRight, // Mueve el container verde abajo a la derecha | ||
| + | child: Container( | ||
| + | height: 150.0, | ||
| + | width: 150.0, | ||
| + | color: Colors.green, | ||
| + | child: Align( | ||
| + | alignment: Alignment.bottomLeft, // Mueve el icono dentro del contenedor verde, abajo a la izquierda | ||
| + | child: Icon(Icons.ac_unit,size: 40.0,), | ||
| + | ), | ||
| + | ), | ||
| + | ), | ||
| + | ), | ||
| + | ), | ||
| + | |||
| + | |||
| + | |||
| + | ], | ||
| + | |||
| + | ); | ||
| + | } | ||
| + | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
| + | |||
| + | |||
| + | <br /> | ||
==SizeBox== | ==SizeBox== | ||
Revisión del 10:33 14 ago 2021
Sumario
Introducción
- En las secciones anteriores vimos algunos de los widgets que podemos emplear para visualizar contenidos en una pantalla.
- En esta sección vamos a ver widgets que nos permiten colocar a otros widgets en ciertas posiciones en base a las propiedades que disponga el Widget.
- Vienen a ser el equivalente a divs en HTML.
- Asociado a este punto vamos a ver como identificar y solucionar los problemas que podamos tener de posicionamiento cuando los widgets no queppan en el espacio asignado por su widget contenedor.
Column / Row
- Más información en:
- Estos widgets permiten 'colocar' en forma de fila o columna el cojunto de Widget que se encuentran dentro.
- El widget Column coloca los widgets uno debajo del otro (en una línea vertical)
- El widgert Row coloca los widgets uno al lado del otro (en una línea horizontal).
- No poseen Scroll y por lo tanto los Widgets que lo conforman no deberían ocupar más espacio que el espacio del contenedor donde se encuentren.
- En caso de necesitar un scroll tendríamos que hacer uso de un Widget ListView como ya vimos en la sección anterior.
- Creamos una nueva página en la carpeta pages de nombre columnrow_page.dart
- En todas las páginas haremos lo mismo:
- Importamos la librería de 'material' (recordar que existe un snippet que lo hace automático).
- Creamos una clase (ColumnRowPage) que derive de StatelessWidget (al hacerlo será necesario implementar el método build, ya os da un aviso el Android Studio).
- Los parámetros más usados son:
- children[]: Conjunto de Widget que van a aparecer visualmente.
- MainAxisAlignment: Indicamos como van a posicionarse los children con respecto al eje principal.
- En el caso de Column, el eje principal es el vertical y en el caso de Row, es el eje horizontal.
- CrossAxisAlignment: Indicamos como van a posicionarse los children con respecto al eje perpendicular al principal.
- En el caso de Column, el eje Cross es el horizontal y en el caso de Row, es el eje vertical.
- Veamos una imagen en la que va a quedar más claro a que se refiere cada eje en cada caso:
- Veamos un ejemplo sencillo en el que emplearemos un Column para colocar texto visualmente en forma de filas (recordar que Column coloca a los widget en una línea vertical).
- Dejamos los valores por defecto para cada eje y veremos que los elementos empiezan a colocarse en la parte superior (MainAxisAlignment.start) y horizontalmente están centrados con respecto al espacio que ocupan (CrossAxisAlignment.center), cogiendo como referencia la fila que ocupa más ancho)
import 'package:flutter/material.dart'; class ColumnRowPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Ejemplo de uso de Row y Colum'), ), body: Column( children: [ Text('Texto de la primera fila',style: TextStyle(backgroundColor: Colors.yellow),), Text('Texto de la segunda fila. Este texto es más largo.',style: TextStyle(backgroundColor: Colors.red),), Text('Texto de la tercera fila',style: TextStyle(backgroundColor: Colors.brown),), ], ) ); } }
- Ahora veamos un ejemplo modificando alguno de los parámetros de los ejes:
import 'package:flutter/material.dart'; class ColumnRowPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Ejemplo de uso de Row y Colum'), ), body: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.end, children: [ Text('Texto de la primera fila',style: TextStyle(backgroundColor: Colors.yellow),), Text('Texto de la segunda fila. Este texto es más largo.',style: TextStyle(backgroundColor: Colors.red),), Text('Texto de la tercera fila',style: TextStyle(backgroundColor: Colors.brown),), ], ) ); } }
- Como en Html, estos widgets son 'contenedores' y podemos tener como parte de un children otro contenedor, por lo tanto podemos tener dentro de Row y Column, otros Row y Column de forma anidada...
- Veamos un ejemplo.
- Fijarse que por defecto, tanto Row como Column toman como 'referecia' el widget que ocupa más espacio.
- En el siguiente ejemplo, el Widget Row está alineado en el CrossAxis al final (CrossAxisAlignment.end) y como uno de los iconos es más alto, el resto se sitúa en la parte baja del mismo.
import 'package:flutter/material.dart'; class ColumnRowPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Ejemplo de uso de Row y Colum'), ), body: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ Text('Texto de la primera fila',style: TextStyle(backgroundColor: Colors.yellow),), Row( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.end, children: [ Icon(Icons.favorite, size: 50,), Icon(Icons.audiotrack, size: 100,), Icon(Icons.cast, size:50,), ], ), Text('Texto de la tercera fila',style: TextStyle(backgroundColor: Colors.brown),), ], ) ); } }
Expanded
- Asociado al widget Row y Column se suele utilizar el widget Expanded, que permite 'expandir' el tamaño del widget hasta el tamaño de su contenedor en su MainAxis.
- Recordar que en Android Studio y en otros ide´s podéis 'envolver' un Widget con otro Widget, situándonos sobre él y pulsando las teclas ALT+Enter aparece la opción Wrap...
- Entre los parámetros a enviar tenemos:
- child: Es el widget que queremos que se expanda. Obligatorio.
- flex: Este parámetro es equivalente a emplear un LinearLayout en Android Studio. Cuando tenemos varios widget´s que se expanden, permite darle un peso a cada uno de ellos para hacer que uno ocupe más que el otro.
- Veamos un ejemplo:
- En este caso, estamos expandiendo en el widget Column, el widget Row para que ocupe todo el espacio entre los dos textos.
- Por otro lado, dentro del Row, estamos expandiendo dos iconos y hacemos que el grande ocupe 3/6 partes del espacio de la fila y el icono de la derecha las 2/6 partes.
- Para poder visualizar el espacio que están ocupando, envolví el Widget Icon con un Container, que explicaré en las siguientes secciones y que nos permite establecer un color de fondo.
import 'package:flutter/material.dart'; class ColumnRowPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Ejemplo de uso de Row y Colum'), ), body: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ Text('Texto de la primera fila',style: TextStyle(backgroundColor: Colors.yellow),), Expanded( child: Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.end, children: [ Expanded(child: Container(child: Icon(Icons.favorite, size: 50,),color: Colors.yellow,),flex: 1,), Expanded(child: Container(child: Icon(Icons.audiotrack, size: 100,),color: Colors.blue),flex:3), Expanded(child: Container(child: Icon(Icons.cast, size:50,),color: Colors.red,),flex: 2,), ], ), ), Text('Texto de la tercera fila',style: TextStyle(backgroundColor: Colors.brown),), ], ) ); } }
- Nota: Como podéis comprobar Expanded sólo afecta el eje principal. Si quisiérais que un icono ocupe todo el alto disponible, podéis modificar la propiedad height del Container y darle el valor double.infinity.
Container
- Más información en https://api.flutter.dev/flutter/widgets/Container-class.html
- Creamos una nueva página en la carpeta pages de nombre container_page.dart
- En todas las páginas haremos lo mismo:
- Importamos la librería de 'material' (recordar que existe un snippet que lo hace automático).
- Creamos una clase (ContainerPage) que derive de StatelessWidget (al hacerlo será necesario implementar el método build, ya os da un aviso el Android Studio).
- Contenedor que permite 'envolver' cualquier widget y con el cual podemos establecer un tamaño, padding y margin.
- La diferencia entre margin y padding es la misma que en HTML con sus div´s.
- Todos los contenidos conforman un contenedor de forma rectangular que lo rodea. El marign es el espacio que hay entre dos contenedores y el padding es el espacio que hay entre el contenido y su contenedor. Más información en este enlace.
- Al establecer un margin y un padding podemos indicar en qué dirección queremos que se aplica esa modificación.
- Para facilitarnos el establecer estos valores haremos uso de la clase EdgeInsets que permite emplear diferentes métodos:
- all: establece un margin-padding en todas las direcciones.
- symmetric: establece un margin-padding simétrico, es decir, se envían dos valores, uno de ellos establece el margin-padding inferior y superior y otro establece el margin-padding derecho e izquierdo.
- only: indicamos sobre que lados vamos a establecer el margin-padding.
- Veamos un ejemplo.
- En este caso voy a hacer uso de la clase MediaQuery para obtener información del ancho de la pantalla y así poder establecer un ancho de uno de los contenedores en base a un porcentaje de dicho ancho.
import 'package:flutter/material.dart'; class ContainerPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Ejemplo de contenedores'), ), body: _conjuntoContenedores(context) // Le pasamos el context para establecer un ancho en porcentaje de la pantalla, lo necesita la clase MediaQuery ); } Widget _conjuntoContenedores(BuildContext context){ return Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ Container( width: double.infinity, // De ancho todo el espacio disponible height: 50.0, color: Colors.red, margin: EdgeInsets.only(bottom: 20.0), // Establece un margin sólo en la parte inferior padding: EdgeInsets.all(10.0), // Establece un padding en las cuatro direcciones child: Text('CONTENEDOR 1',textAlign: TextAlign.center,), ), Expanded( flex: 2, child: Container( padding: EdgeInsets.only(top:20.0,left: 20.0), margin: EdgeInsets.only(top: 30.0), width: MediaQuery.of(context).size.width*0.5, color: Colors.blue, child: Text('CONTENEDOR 2'), ), ), Expanded( flex: 2, child: Container( margin: EdgeInsets.all(10.0), // Establece un margin de 10 en todas las direcciones alignment: Alignment.center, // Expande horizontalmente y centra color: Colors.yellow, child: Text('CONTENEDOR 3'), ), ), ], ); } }
Align / Center
- Más información en:
- Creamos una nueva página en la carpeta pages de nombre aligncenter_page.dart
- En todas las páginas haremos lo mismo:
- Importamos la librería de 'material' (recordar que existe un snippet que lo hace automático).
- Creamos una clase (AlignCenterPage) que derive de StatelessWidget (al hacerlo será necesario implementar el método build, ya os da un aviso el Android Studio).
- Normalmente son usados cuando queramos centrar o alinear un único widget. La diferencia entre Align y Center es que con Align podemos establecer donde situar al Widget dentro de su contenedor (arriba-abajo, izquierda-derecha) mientras que con Center siempre lo va a centrar.
import 'package:flutter/material.dart'; class AlignCenterPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Ejemplo de Align y Center'), ), body: _conjuntoContenedores() ); } Widget _conjuntoContenedores(){ return Column( children: [ Center( child: Container( height: 150.0, width: 150.0, color: Colors.yellow, child: Center(child: Icon(Icons.access_alarm,size: 40.0,)), ), ), Align( alignment: Alignment.centerRight, // Es igual que sea top o botton. Sólo hace uso del right al usar Column child: Container( height: 150.0, width: 150.0, color: Colors.red, child: Align( alignment: Alignment.bottomLeft, // Sitúa al icono abajo a la izquierda con respecto a su contenedor child: Icon(Icons.ac_unit,size: 40.0,), ), ), ), Expanded( child: Container( // Creo un container que ocupe todo el espacio restante color: Colors.brown, child: Align( alignment: Alignment.bottomRight, // Mueve el container verde abajo a la derecha child: Container( height: 150.0, width: 150.0, color: Colors.green, child: Align( alignment: Alignment.bottomLeft, // Mueve el icono dentro del contenedor verde, abajo a la izquierda child: Icon(Icons.ac_unit,size: 40.0,), ), ), ), ), ), ], ); } }
SizeBox
Debugger Diseño
- Debugger de diseño. Verificar el tamaño de las cajas de cada widget y localizar cual de ellas produce un error
Enlaces de interés
- https://flutter.dev/docs/development/ui/layout
- https://esflutter.dev/docs/development/ui/layout#organiza-multiples-widgets-vertical-y-horizontalmente
- https://medium.com/comunidad-flutter/construya-uis-responsivas-en-flutter-f528d16b50a4
- https://medium.com/flutter-community/developing-for-multiple-screen-sizes-and-orientations-in-flutter-fragments-in-flutter-a4c51b849434
- https://medium.com/flutter-community/build-responsive-uis-in-flutter-fd450bd59158
Enlace a la página principal de la UD3
Enlace a la página principal del curso
-- Ángel D. Fernández González -- (2021).
