Widgets para construir tu página
Al igual que en un sitio web, una aplicación móvil se presenta en forma de «páginas» a través de las cuales el usuario puede navegar. La primera tarea es crear un widget de tipo MaterialApp(), que contendrá un Scaffold() (estructura), el cual servirá como esqueleto de la aplicación. Dentro de este Scaffold, colocaremos el body() (cuerpo) de nuestra app, así como una posible AppBar() o una BottomAppBar().
Scaffold
El Scaffold es el widget que se coloca en el parámetro home de tu MaterialApp(). Si la MaterialApp() actúa como un lienzo en blanco, el Scaffold es más bien el esqueleto de tu app, que permite construir los elementos visuales. Este se compone de tres parámetros opcionales, pero importantes:
- appBar, que toma como argumento un widget de tipo AppBar().
- body, que puede tomar como argumento un Container, Center(), una columna, etc.
- bottomNavigationBar, que toma como argumento un widget de tipo BottomAppBar().
Con estos tres elementos, podrás comenzar a construir el aspecto visual de tu aplicación.
Puedes utilizar este código para empezar a practicar y entender cómo los widgets se «anidan» unos dentro de otros:
void main() => runApp(const MonExempleDeScaffold());
class MonExempleDeScaffold extends StatelessWidget {
const MonExempleDeScaffold({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: ExempleScaffold(),
);
}
}
class ExempleScaffold extends StatefulWidget {
const ExempleScaffold({super.key});
@override
State<ExempleScaffold> createState() => _ExempleScaffoldState();
}
class _ExempleScaffoldState extends State<ExempleScaffold> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.blueGrey.shade200,
title: const Text('AppBar de ejemplo'),
),
body: Center(child: Text('Aquí está el cuerpo de mi aplicación')),
backgroundColor: Colors.white,
);
}
}
Aquí, mi función runApp() lanza mi MaterialApp(), sobre la cual descansa mi Scaffold() que contiene todos los elementos visuales de mi página.
AppBar
El widget AppBar() se refiere a una banda en la parte superior de la pantalla donde puedes insertar otros widgets, como texto, íconos o botones. Por ejemplo, puedes usarlo para crear un menú en la parte superior de tu página o para reservar un espacio para que el contenido de la aplicación no sea ocultado por la cámara del teléfono.
BottomAppBar
El BottomAppBar() funciona de manera similar a la AppBar, pero en la parte inferior de tu teléfono. Un uso común es crear un menú de íconos que permita navegar por las secciones de tu aplicación. Por ejemplo, aquí tienes un menú que creé utilizando este widget, donde coloqué una TabBar().
Te comparto el código que puedes reutilizar y personalizar según tus necesidades.
class PantallaInicio extends StatefulWidget {
const PantallaInicio({super.key});
@override
State<PantallaInicio> createState() => _PantallaInicioState();
}
class _PantallaInicioState extends State<PantallaInicio> {
@override
Widget build(BuildContext context) {
return Scaffold(
extendBody: true,
backgroundColor: Colors.white,
bottomNavigationBar: BottomAppBar(
color: Colors.transparent,
elevation: 0,
child: menu(),
),
body: const TabBarView(
children: [
Pagina1(),
Pagina2(),
/*
Aquí es donde debes colocar tus diferentes páginas, cuyo número debe ser igual al de las pestañas (Tabs). Añade o quita pestañas según tus necesidades.
*/
],
));
}
Widget menu() {
return Container(
margin: EdgeInsets.only(right: 25, left: 25),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(40),
border: Border.all(
width: 0.05,
color: Color.fromARGB(255, 24, 83, 79),
),
color: Colors.white.withOpacity(0.9),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.2),
spreadRadius: 2,
blurRadius: 5,
offset: Offset(0, 5),
),
]),
child: TabBar(
labelPadding: EdgeInsets.all(5),
labelColor: Color.fromARGB(255, 33, 46, 83),
dividerColor: Colors.transparent,
unselectedLabelColor: Color.fromARGB(255, 33, 46, 83).withOpacity(0.4),
indicatorSize: TabBarIndicatorSize.label,
indicatorPadding: EdgeInsets.only(bottom: 5.0),
indicatorColor: Color.fromARGB(255, 206, 106, 107),
tabs: const [
Tab(
icon: Icon(
Ionicons.home,
size: 27,
),
),
Tab(
icon: Icon(
Ionicons.school,
size: 27,
),
),
],
),
);
}
}
Widgets de filas y columnas
Una vez que hayas creado tu página, podrás agregar botones, imágenes, áreas de texto, etc. Sin embargo, supongo que querrás posicionarlos en un lugar exacto de tu aplicación y no de manera aleatoria. Es aquí donde los widgets Row()
(fila) y Column()
(columna) te serán útiles.
Estos dos widgets, como sus nombres lo indican, te permiten apilar varios widgets ya sea en sentido vertical (columna) o en sentido horizontal (fila). Son especialmente importantes porque un simple Container()
solo puede contener un widget en su parámetro child. Esto significa que, por ejemplo, solo podrías colocar un texto en un Container()
. Los widgets Row()
y Column()
solucionan este problema al permitirte agregar tantos widgets como desees en su parámetro children.
Aquí tienes un ejemplo simple del uso de los widgets Row()
y Column()
:
class EjemploFilaColumna extends StatefulWidget {
const EjemploFilaColumna({super.key});
@override
State<EjemploFilaColumna> createState() => _EjemploFilaColumnaState();
}
class _EjemploFilaColumnaState extends State<EjemploFilaColumna> {
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
color: Colors.purple,
height: MediaQuery.of(context).size.height * 0.08,
width: MediaQuery.of(context).size.width * 0.3,
child: TextButton(
onPressed: () {
},
child: const Text(
"Conexión",
style: TextStyle(color: Colors.white),
))),
Container(
color: Colors.red,
height: MediaQuery.of(context).size.height * 0.08,
width: MediaQuery.of(context).size.width * 0.3,
child: TextButton(
onPressed: () {
},
child: const Text(
"Desconexión",
style: TextStyle(color: Colors.white),
))),
],
),
);
}
}
Widgets para añadir contenido
Ya has construido tu página y sabes cómo organizar el contenido en ella. Ahora es el momento de añadir tus diferentes elementos visuales.
Container
El widget Container()
te permite crear un área rectangular. Puedes darle un alto, un ancho, un color, márgenes, bordes, etc. Lo más importante es que puedes colocar un widget hijo dentro de él, que llenará el espacio. El Container()
es, por lo tanto, una buena manera de delimitar un área en la que colocarás un elemento visual de tu aplicación, como una zona de texto, una imagen, un botón, etc.
Text
El widget Text()
, como su nombre lo indica, te permite agregar elementos textuales a tu aplicación. Este widget viene con diferentes parámetros que te permiten definir el estilo de tu texto, como su color, tamaño, grosor, etc.
Image
Añadir imágenes es también algo importante cuando creas una aplicación, por ejemplo, para una página de perfil. Flutter facilita la integración de elementos visuales con su widget Image()
, que puedes utilizar de las siguientes maneras:
.asset()
-> Permite integrar imágenes o GIFs almacenados en las carpetas de tu aplicación y añadidos en tu archivo pubspec.yaml;.network()
-> Permite integrar imágenes o GIFs accesibles en línea mediante su URL.
Icon
Al igual que las imágenes, los íconos son elementos visuales importantes para construir una aplicación, especialmente para crear botones. El widget Icon()
te permite agregar un ícono a tu aplicación y modificar su estilo, como el color, tamaño, etc.
ElevatedButton
Para permitir que tus usuarios interactúen con tu aplicación, necesitarás agregar botones. La forma más simple de hacerlo es usando el widget ElevatedButton
. Este widget te permite crear casi cualquier tipo de botón, ya sea a partir de una forma, un texto o un ícono, e integrarle una función. Por ejemplo:
Container(
height: MediaQuery.of(context).size.height * 0.06,
width: MediaQuery.of(context).size.width * 0.5,
child: ElevatedButton(
onPressed: () {
print("Mi botón funciona");
},
style: ElevatedButton.styleFrom(
surfaceTintColor: Colors.white,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(30))),
side: const BorderSide(
color: Colors.black, width: 1)),
child: const Text("Botón de prueba",
style: TextStyle(color: Colors.black))))
Conclusión
Estos widgets son la base de cualquier aplicación y son un buen punto de partida para construir la tuya. Aprende a usarlos jugando con sus diferentes propiedades e intenta reproducir los elementos visuales de otras aplicaciones. Si quieres aprender más, he escrito una guía para cada uno de ellos:
- Guía completa Flutter: el widget
Scaffold
; - Guía completa Flutter: el widget
Container
; - Guía completa Flutter: el widget
Column
; - Guía completa Flutter: el widget
Row
; - Guía completa Flutter: el widget
Text
; - Guía completa Flutter: el widget
Icon
; - Guía completa Flutter: el widget
Image
; - Guía completa Flutter: el widget
ElevatedButton
.
Una vez que domines la creación de la interfaz de tu aplicación, será hora de enfocarte en el backend. ¿Cómo almacenarás los datos y los transmitirás a tus usuarios? ¿Cómo gestionarás las cuentas de usuario y la autenticación? Te doy la respuesta en el siguiente artículo:
Construir el backend de tu aplicación con Firebase →