En esta sección, aprenderemos sobre los widgets de entrada y formularios en Flutter. Estos widgets son esenciales para crear aplicaciones interactivas que requieran la entrada de datos por parte del usuario. Cubriremos los siguientes temas:
- TextField
- Form
- FormField
- Checkbox
- Radio
- Switch
- DropdownButton
- ElevatedButton
- TextField
El widget TextField
es el más común para la entrada de texto. Permite a los usuarios escribir y editar texto.
Ejemplo Básico de TextField
import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: Text('TextField Example')), body: Padding( padding: const EdgeInsets.all(16.0), child: TextField( decoration: InputDecoration( border: OutlineInputBorder(), labelText: 'Enter your name', ), ), ), ), ); } }
Explicación
TextField
: Widget para la entrada de texto.InputDecoration
: Proporciona decoraciones como bordes y etiquetas para elTextField
.OutlineInputBorder
: Añade un borde alrededor delTextField
.labelText
: Texto que se muestra como etiqueta dentro delTextField
.
- Form
El widget Form
agrupa varios widgets de entrada y permite validarlos de manera conjunta.
Ejemplo Básico de Form
import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: Text('Form Example')), body: MyCustomForm(), ), ); } } class MyCustomForm extends StatefulWidget { @override _MyCustomFormState createState() => _MyCustomFormState(); } class _MyCustomFormState extends State<MyCustomForm> { final _formKey = GlobalKey<FormState>(); @override Widget build(BuildContext context) { return Form( key: _formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ TextFormField( decoration: InputDecoration( labelText: 'Enter your name', ), validator: (value) { if (value == null || value.isEmpty) { return 'Please enter some text'; } return null; }, ), Padding( padding: const EdgeInsets.symmetric(vertical: 16.0), child: ElevatedButton( onPressed: () { if (_formKey.currentState!.validate()) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Processing Data')), ); } }, child: Text('Submit'), ), ), ], ), ); } }
Explicación
Form
: Widget que agrupa y gestiona varios widgets de entrada.GlobalKey<FormState>
: Clave global para identificar el estado del formulario.TextFormField
: Similar aTextField
, pero con validación integrada.validator
: Función que valida la entrada del usuario.ElevatedButton
: Botón que, al ser presionado, valida el formulario.
- FormField
El widget FormField
es una clase base para widgets que se utilizan dentro de un Form
.
Ejemplo Básico de FormField
import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: Text('FormField Example')), body: MyCustomForm(), ), ); } } class MyCustomForm extends StatefulWidget { @override _MyCustomFormState createState() => _MyCustomFormState(); } class _MyCustomFormState extends State<MyCustomForm> { final _formKey = GlobalKey<FormState>(); @override Widget build(BuildContext context) { return Form( key: _formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ FormField<String>( builder: (FormFieldState<String> state) { return TextFormField( decoration: InputDecoration( labelText: 'Enter your name', ), validator: (value) { if (value == null || value.isEmpty) { return 'Please enter some text'; } return null; }, ); }, ), Padding( padding: const EdgeInsets.symmetric(vertical: 16.0), child: ElevatedButton( onPressed: () { if (_formKey.currentState!.validate()) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Processing Data')), ); } }, child: Text('Submit'), ), ), ], ), ); } }
Explicación
FormField
: Clase base para widgets dentro de unForm
.FormFieldState
: Estado delFormField
.
- Checkbox
El widget Checkbox
permite a los usuarios seleccionar o deseleccionar una opción.
Ejemplo Básico de Checkbox
import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: Text('Checkbox Example')), body: MyCheckboxWidget(), ), ); } } class MyCheckboxWidget extends StatefulWidget { @override _MyCheckboxWidgetState createState() => _MyCheckboxWidgetState(); } class _MyCheckboxWidgetState extends State<MyCheckboxWidget> { bool _isChecked = false; @override Widget build(BuildContext context) { return Center( child: CheckboxListTile( title: Text('Accept Terms and Conditions'), value: _isChecked, onChanged: (bool? value) { setState(() { _isChecked = value!; }); }, ), ); } }
Explicación
CheckboxListTile
: Combina unCheckbox
con unListTile
.value
: Estado actual delCheckbox
.onChanged
: Función que se llama cuando el estado delCheckbox
cambia.
- Radio
El widget Radio
permite a los usuarios seleccionar una opción de un conjunto de opciones.
Ejemplo Básico de Radio
import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: Text('Radio Example')), body: MyRadioWidget(), ), ); } } class MyRadioWidget extends StatefulWidget { @override _MyRadioWidgetState createState() => _MyRadioWidgetState(); } class _MyRadioWidgetState extends State<MyRadioWidget> { String? _selectedOption = 'Option 1'; @override Widget build(BuildContext context) { return Column( children: <Widget>[ ListTile( title: Text('Option 1'), leading: Radio<String>( value: 'Option 1', groupValue: _selectedOption, onChanged: (String? value) { setState(() { _selectedOption = value; }); }, ), ), ListTile( title: Text('Option 2'), leading: Radio<String>( value: 'Option 2', groupValue: _selectedOption, onChanged: (String? value) { setState(() { _selectedOption = value; }); }, ), ), ], ); } }
Explicación
Radio
: Widget para seleccionar una opción.value
: Valor de la opción.groupValue
: Valor del grupo de opciones.onChanged
: Función que se llama cuando se selecciona una opción.
- Switch
El widget Switch
permite a los usuarios alternar entre dos estados, como encendido y apagado.
Ejemplo Básico de Switch
import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: Text('Switch Example')), body: MySwitchWidget(), ), ); } } class MySwitchWidget extends StatefulWidget { @override _MySwitchWidgetState createState() => _MySwitchWidgetState(); } class _MySwitchWidgetState extends State<MySwitchWidget> { bool _isSwitched = false; @override Widget build(BuildContext context) { return Center( child: SwitchListTile( title: Text('Enable Notifications'), value: _isSwitched, onChanged: (bool value) { setState(() { _isSwitched = value; }); }, ), ); } }
Explicación
SwitchListTile
: Combina unSwitch
con unListTile
.value
: Estado actual delSwitch
.onChanged
: Función que se llama cuando el estado delSwitch
cambia.
- DropdownButton
El widget DropdownButton
permite a los usuarios seleccionar una opción de un menú desplegable.
Ejemplo Básico de DropdownButton
import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: Text('DropdownButton Example')), body: MyDropdownButtonWidget(), ), ); } } class MyDropdownButtonWidget extends StatefulWidget { @override _MyDropdownButtonWidgetState createState() => _MyDropdownButtonWidgetState(); } class _MyDropdownButtonWidgetState extends State<MyDropdownButtonWidget> { String? _selectedItem = 'Item 1'; @override Widget build(BuildContext context) { return Center( child: DropdownButton<String>( value: _selectedItem, items: <String>['Item 1', 'Item 2', 'Item 3'].map((String value) { return DropdownMenuItem<String>( value: value, child: Text(value), ); }).toList(), onChanged: (String? newValue) { setState(() { _selectedItem = newValue; }); }, ), ); } }
Explicación
DropdownButton
: Widget para seleccionar una opción de un menú desplegable.value
: Valor actual seleccionado.items
: Lista de opciones.onChanged
: Función que se llama cuando se selecciona una opción.
- ElevatedButton
El widget ElevatedButton
es un botón elevado que se utiliza para realizar acciones.
Ejemplo Básico de ElevatedButton
import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: Text('ElevatedButton Example')), body: Center( child: ElevatedButton( onPressed: () { print('Button Pressed'); }, child: Text('Press Me'), ), ), ), ); } }
Explicación
ElevatedButton
: Botón elevado.onPressed
: Función que se llama cuando se presiona el botón.child
: Contenido del botón, generalmente unText
.
Ejercicio Práctico
Ejercicio
Crea una aplicación que tenga un formulario con los siguientes campos:
- Nombre (TextField)
- Correo Electrónico (TextField)
- Aceptar Términos y Condiciones (Checkbox)
- Género (Radio)
- País (DropdownButton)
- Botón de Enviar (ElevatedButton)
Solución
import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: Text('Form Example')), body: MyCustomForm(), ), ); } } class MyCustomForm extends StatefulWidget { @override _MyCustomFormState createState() => _MyCustomFormState(); } class _MyCustomFormState extends State<MyCustomForm> { final _formKey = GlobalKey<FormState>(); bool _isChecked = false; String? _selectedGender = 'Male'; String? _selectedCountry = 'USA'; @override Widget build(BuildContext context) { return Form( key: _formKey, child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ TextFormField( decoration: InputDecoration( labelText: 'Enter your name', ), validator: (value) { if (value == null || value.isEmpty) { return 'Please enter some text'; } return null; }, ), TextFormField( decoration: InputDecoration( labelText: 'Enter your email', ), validator: (value) { if (value == null || value.isEmpty) { return 'Please enter some text'; } return null; }, ), CheckboxListTile( title: Text('Accept Terms and Conditions'), value: _isChecked, onChanged: (bool? value) { setState(() { _isChecked = value!; }); }, ), ListTile( title: Text('Male'), leading: Radio<String>( value: 'Male', groupValue: _selectedGender, onChanged: (String? value) { setState(() { _selectedGender = value; }); }, ), ), ListTile( title: Text('Female'), leading: Radio<String>( value: 'Female', groupValue: _selectedGender, onChanged: (String? value) { setState(() { _selectedGender = value; }); }, ), ), DropdownButton<String>( value: _selectedCountry, items: <String>['USA', 'Canada', 'Mexico'].map((String value) { return DropdownMenuItem<String>( value: value, child: Text(value), ); }).toList(), onChanged: (String? newValue) { setState(() { _selectedCountry = newValue; }); }, ), Padding( padding: const EdgeInsets.symmetric(vertical: 16.0), child: ElevatedButton( onPressed: () { if (_formKey.currentState!.validate()) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Processing Data')), ); } }, child: Text('Submit'), ), ), ], ), ), ); } }
Explicación
- Se combinan varios widgets de entrada y un botón de envío dentro de un
Form
. - Se utiliza
CheckboxListTile
,Radio
,DropdownButton
, yElevatedButton
para crear un formulario completo.
Conclusión
En esta sección, hemos aprendido sobre los widgets de entrada y formularios en Flutter. Estos widgets son fundamentales para crear aplicaciones interactivas y recolectar datos de los usuarios. Hemos cubierto TextField
, Form
, FormField
, Checkbox
, Radio
, Switch
, DropdownButton
, y ElevatedButton
, y hemos visto cómo combinarlos en un formulario completo. Con estos conocimientos, estás listo para crear formularios más complejos y manejar la entrada de datos en tus aplicaciones Flutter.
Curso de Desarrollo con Flutter
Módulo 1: Introducción a Flutter
- ¿Qué es Flutter?
- Configuración del Entorno de Desarrollo
- Entendiendo la Arquitectura de Flutter
- Creando Tu Primera App con Flutter
Módulo 2: Conceptos Básicos de Programación en Dart
- Introducción a Dart
- Variables y Tipos de Datos
- Sentencias de Control de Flujo
- Funciones y Métodos
- Programación Orientada a Objetos en Dart
Módulo 3: Widgets en Flutter
- Introducción a los Widgets
- Widgets Stateless vs Stateful
- Widgets Básicos
- Widgets de Diseño
- Widgets de Entrada y Formularios
Módulo 4: Gestión de Estado
Módulo 5: Navegación y Enrutamiento
- Introducción a la Navegación
- Navegación Básica
- Rutas Nombradas
- Pasando Datos Entre Pantallas
- Deep Linking
Módulo 6: Redes y APIs
- Obteniendo Datos de Internet
- Parseo de Datos JSON
- Manejo de Errores de Red
- Usando APIs REST
- Integración con GraphQL
Módulo 7: Persistencia y Almacenamiento
- Introducción a la Persistencia
- Preferencias Compartidas
- Almacenamiento de Archivos
- Base de Datos SQLite
- Usando Hive para Almacenamiento Local
Módulo 8: Conceptos Avanzados de Flutter
- Animaciones en Flutter
- Custom Paint y Canvas
- Canales de Plataforma
- Isolates y Concurrencia
- Optimización de Rendimiento
Módulo 9: Pruebas y Depuración
- Introducción a las Pruebas
- Pruebas Unitarias
- Pruebas de Widgets
- Pruebas de Integración
- Técnicas de Depuración
Módulo 10: Despliegue y Mantenimiento
- Preparación para el Lanzamiento
- Construcción para iOS
- Construcción para Android
- Integración Continua/Despliegue Continuo (CI/CD)
- Mantenimiento y Actualización de Tu App