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 unCheckboxcon unListTile.value: Estado actual delCheckbox.onChanged: Función que se llama cuando el estado delCheckboxcambia.
- 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 unSwitchcon unListTile.value: Estado actual delSwitch.onChanged: Función que se llama cuando el estado delSwitchcambia.
- 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, yElevatedButtonpara 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
