Los widgets, la piedra angular de Flutter
En el capítulo anterior hemos visto los orígenes del framework Flutter, quién lo creó, un poco sobre …
leer másFlutter es un framework de desarrollo de aplicaciones móviles creado por Google que ha ganado popularidad por su capacidad para construir aplicaciones de alta calidad con una única base de código, ya hemos hablado de ello anteriormente en profundidad. También hemos visto que uno de los pilares fundamentales de Flutter es su enfoque en los Widgets. En Flutter, todo es un widget. Desde el más simple texto hasta las complejas interfaces de usuario, todo se construye utilizando Widgets. Esto simplifica enormemente el desarrollo y proporciona flexibilidad para los desarrolladores. Si recién empiezas con Flutter te recomiendo leer los capítulos anteriores de la serie antes de continuar.
Un widget en Flutter es un componente de la interfaz de usuario que describe una parte de la misma. Forman la base de una aplicación y pueden ser de diferentes tipos, como botones, textos, imágenes, listas, entre otros. Éstos no sólo definen la estructura y apariencia de la interfaz, sino también cómo se comporta y reacciona a la interacción del usuario.
Ya hemos visto que por defecto, Flutter, diferencia dos tipos de widgets: StatelessWidget
y StatefulWidget
. Ahora vamos a profundizar en algunos de los widgets más comunes y útiles que se utilizan en el desarrollo
de aplicaciones Flutter para dar forma y estructura a nuestra interfaz de usuario.
Además de los StatelessWidget
y StatefulWidget
, Flutter proporciona una amplia gama de Widgets
incorporados que cubren casi todas las necesidades del desarrollo de aplicaciones para móviles, se pueden clasificar en
varias categorías.
Los widgets de disposición son responsables de organizar y posicionar los widgets en la pantalla. Algunos de los widgets de disposición junto a sus parámetros más comunes son:
Row: Organiza sus hijos en una fila horizontal.
Column: Organiza sus hijos en una columna vertical.
Container: Permite personalizar la apariencia de sus hijos, como el color de fondo, el margen, el relleno, etc.
Padding: Añade relleno a sus hijos.
Center: Centra a sus hijos en la pantalla.
Expanded: Expande a su hijo para ocupar todo el espacio disponible.
SizedBox: Contenedor que impone un tamaño fijo a sus hijos.
ListView: Muestra una lista de elementos desplazables.
GridView: Presenta una cuadrícula de elementos.
Stack: Apila a sus hijos uno encima del otro.
Align: Alinea a sus hijos dentro de sí mismo.
Los widgets de visualización son responsables de mostrar información en la pantalla. Algunos de los widgets de los más comunes son:
Text: Despliega texto en la pantalla. Se debe introducir el texto a mostrar como primer parámetro.
Image: Renderiza una imagen en la pantalla.
Icon: Muestra un icono en la pantalla.
Card: Presenta una tarjeta con una sombra y esquinas normalmente redondeadas.
Chip: Exhibe una etiqueta con un icono y un texto.
Divider: Inserta una línea divisoria entre elementos.
Tooltip: Proporciona un mensaje emergente informativo.
SnackBar: Ofrece un mensaje emergente temporal.
CircularProgressIndicator: Indica el progreso con un círculo.
LinearProgressIndicator: Representa el progreso de forma lineal.
AppBar: Proporciona una barra de aplicaciones en la parte superior de la pantalla.
Drawer: Despliega un panel deslizable desde el borde de la pantalla.
Dialog: Muestra una caja de diálogo que aparece encima del contenido principal.
AlertDialog: Muestra una caja de diálogo encima del contenido principal con acciones personalizadas. Todos los AlertDialog
son Dialog
pero no todos los Dialog
son AlertDialog
.
Los widgets de acción son responsables de manejar la interacción del usuario. Algunos de los widgets de botón más comunes son:
ElevatedButton: Presenta un botón elevado con un fondo de color.
TextButton: Ofrece un botón de texto sin fondo.
IconButton: Despliega un botón con un icono.
FloatingActionButton: Muestra un botón flotante circular.
PopupMenuButton: Despliega un menú emergente.
DropdownButton: Presenta un menú desplegable.
OutlinedButton: Ofrece un botón con un borde pero sin fondo.
Los widgets de entrada son responsables de recoger información del usuario. Algunos de los widgets de entrada más comunes son:
TextField: Permite al usuario introducir texto.
Slider: Muestra un control deslizante.
Checkbox: Presenta una casilla de verificación.
Switch: Muestra un interruptor de encendido y apagado.
Radio: Proporciona un botón de opción.
Form: Agrupa varios campos de entrada y proporciona validación.
Gracias a todos estos Widgets y a la flexibilidad que proporciona Flutter, podemos construir interfaces de usuario complejas y atractivas con facilidad para aplicaciones móviles con una apariencia y funcionalidad excepcionales. Hay muchísimos más y aun encima pueden extenderse con widgets personalizados propios o ya creados por la comunidad. Sólo utilizando algunos de los aquí listados puedes hacer algo parecido a lo que se muestra en la captura siguiente, si quieres conocer su código fuente continúa leyendo.
Para nuestro ejemplo vamos a combinar algunos de estos widgets y así construir una interfaz de usuario llamativa y funcional.
En él veremos varios de los diferentes tipos de widgets que hemos mencionado hasta ahora, como puede ser el Drawer
:
Drawer(
child: SizedBox(
height: double.infinity,
width: 200,
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
DrawerHeader(
decoration: BoxDecoration(
color: Theme.of(context).primaryColor,
),
child: Text(
'Drawer Header',
style: TextStyle(
color: Colors.white,
fontSize: 24,
),
),
),
ListTile(
leading: Icon(Icons.home),
title: Text('Home'),
onTap: () {
Navigator.pop(context);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Home tapped'),
),
);
},
),
ListTile(
leading: Icon(Icons.settings),
title: Text('Settings'),
onTap: () {
Navigator.pop(context);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Settings tapped'),
),
);
},
),
],
),
)
)
En este ejemplo, hemos utilizado el Widget Drawer
para mostrar un panel deslizable con dos elementos: Home
y Settings
como
muestra de un menú lateral típico en muchas aplicaciones móviles. Al seleccionar uno de los elementos, en nuestro caso,
se muestra un SnackBar
con un mensaje informativo pero podríamos navegar a otra pantalla o realizar cualquier otra acción.
Otro de los widgets destacables es el FloatingActionButton
que se muestra en la esquina inferior derecha de la pantalla.
Este botón flotante circular es muy común en las aplicaciones móviles y se utiliza para acciones destacadas o comunes, en
nuestro caso simplemente mostramos un diálogo al pulsarlo:
FloatingActionButton(
onPressed: () {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text('Alert Dialog'),
content: Text('This is an alert dialog where you can cancel or confirm.'),
actions: [
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('Cancel'),
),
TextButton(
onPressed: () {
Navigator.pop(context);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('You are now a new member of the club!'),
),
);
},
child: Text('Confirm'),
),
],
);
},
);
},
child: Icon(Icons.info),
)
En el ejemplo anterior vemos la combinación de dos Widgets entre sí para mostrar un diálogo con dos botones de acción tras presionar el botón flotante. Para nuestro ejemplo está todo en el mismo lugar pero quizá lo conveniente sería modularizar el código y separar los diferentes elementos en diferentes lugares para mantener una estructura limpia y ordenada.
El widget de navegación inferior BottomNavigationBar
es otro de los widgets comunes en las aplicaciones móviles. En este
caso hemos utilizado un BottomNavigationBar
con tres elementos: Home
, Search
y Profile
. Al seleccionar uno de los elementos,
la aplicación se mueve a una ventana diferente, similar a la distribución por pestañas pero en la parte inferior de la pantalla:
BottomNavigationBar(
currentIndex: _selectedIndex,
onTap: _onItemTapped,
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.search),
label: 'Search',
),
BottomNavigationBarItem(
icon: Icon(Icons.person),
label: 'Profile',
),
],
)
Los Widgets interactivos incluidos en la aplicación de ejemplo como el Switch
, el Slider
o el Checkbox
son elementos
bastante comunes también en aplicaciones móviles y se utilizan para recoger información del usuario. En nuestro código fuente
cada uno de ellos está encapsulado en un Widget Card
para darles un aspecto más atractivo y organizado, el de volumen además,
muestra la información de una forma distinta respecto a los otros dos para hacer la experiencia de usuario más amigable.
Mientras que el Switch
y el Checkbox
sólo tienen dos estados posibles (activado/desactivado), el Slider
permite múltiples
valores decimales entre 0 a 1, no tendría sentido mostrar un Snackbar
cada vez que éste cambie:
Card(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Text('Enable Notifications', style: TextStyle(fontSize: 18)),
Spacer(),
Switch(
value: _isNotificationEnabled,
onChanged: (bool value) {
setState(() {
_isNotificationEnabled = value;
});
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Notifications ${value ? 'enabled' : 'disabled'}'),
),
);
},
),
],
),
),
),
Card(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Text('Dark Mode', style: TextStyle(fontSize: 18)),
Spacer(),
Checkbox(
value: _isDarkModeEnabled,
onChanged: (bool? value) {
setState(() {
_isDarkModeEnabled = value ?? false;
});
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Dark Mode ${value ?? false ? 'enabled' : 'disabled'}'),
)
);
},
),
],
),
),
),
Card(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Text('Volume', style: TextStyle(fontSize: 18, fontStyle: FontStyle.italic)),
SizedBox(width: 20),
Text(_volumeValue.toStringAsFixed(2)),
Spacer(),
Slider(
value: _volumeValue,
onChanged: (double value) {
setState(() {
_volumeValue = value;
});
},
),
],
),
),
),
Y eso ha sido todo para este capítulo de nuestra serie de Flutter, te invito a investigar por ti mismo cómo hemos hecho para combinar algunos de los widgets aquí mencionados y así forma a la interfaz de usuario de nuestra aplicación. El código fuente completo está disponible en nuestro repositorio de Github, allí podrás tanto verlo como descargarlo para probar por ti mismo y hacer las modificaciones que consideres, podrías empezar añadiendo aquellos Widgets de la lista que no hayan sido integrados en la aplicación y familizarizarte con aquellos que no conozcas. Si te ha gustado este artículo y quieres seguir aprendiendo sobre Flutter y otros temas de desarrollo de aplicaciones móviles, coméntanos qué te ha parecido y qué te gustaría ver en futuros artículos y sobre todo ¡Happy Coding!
Quizá te puedan interesar
En el capítulo anterior hemos visto los orígenes del framework Flutter, quién lo creó, un poco sobre …
leer másFlutter es un framework de desarrollo de aplicaciones móviles creado por Google, utiliza el motor de …
leer másAnteriormente, hemos visto cómo funcionan los códigos QR y cómo se pueden utilizar para almacenar en …
leer másDe concepto a realidad