Entrada de usuario en Flutter
Esta sección explica cómo manejar la entrada de usuario en aplicaciones Flutter, incluyendo entrada de texto, clics en botones, manejo de formularios, etc.
TextField - Entrada de texto
TextField es el widget de entrada de texto más utilizado en Flutter.
Ejemplo: Uso básico de TextField
// El TextField más simple
TextField()
// TextField con decoración
TextField(
decoration: const InputDecoration(
labelText: 'Nombre de usuario', // Etiqueta
hintText: 'Ingrese el nombre de usuario', // Texto de sugerencia
prefixIcon: Icon(Icons.person), // Icono prefijo
),
)
// TextField con borde
TextField(
decoration: InputDecoration(
border: OutlineInputBorder( // Borde exterior
borderRadius: BorderRadius.circular(8),
),
labelText: 'Contraseña',
),
obscureText: true, // Ocultar contenido de entrada (escenario de contraseña)
)
// Entrada de texto multilínea
TextField(
maxLines: 3, // Número máximo de líneas
decoration: const InputDecoration(
hintText: 'Ingrese texto multilínea',
),
)
TextField()
// TextField con decoración
TextField(
decoration: const InputDecoration(
labelText: 'Nombre de usuario', // Etiqueta
hintText: 'Ingrese el nombre de usuario', // Texto de sugerencia
prefixIcon: Icon(Icons.person), // Icono prefijo
),
)
// TextField con borde
TextField(
decoration: InputDecoration(
border: OutlineInputBorder( // Borde exterior
borderRadius: BorderRadius.circular(8),
),
labelText: 'Contraseña',
),
obscureText: true, // Ocultar contenido de entrada (escenario de contraseña)
)
// Entrada de texto multilínea
TextField(
maxLines: 3, // Número máximo de líneas
decoration: const InputDecoration(
hintText: 'Ingrese texto multilínea',
),
)
TextEditingController - Controlador de texto
Usando TextEditingController se puede leer y controlar el contenido de TextField.
< h2 class="example">Ejemplo: Uso de TextEditingController
class TextFieldExample extends StatefulWidget {
const TextFieldExample({super.key});
@override
State<TextFieldExample> createState() => _TextFieldExampleState();
}
class _TextFieldExampleState extends State<TextFieldExample> {
// Crear controlador
final TextEditingController _controller = TextEditingController();
String _displayText = '';
@override
void dispose() {
// Destruir controlador
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Column(
children: [
TextField(
controller: _controller, // Vincular controlador
decoration: const InputDecoration(
labelText: 'Ingresar texto',
),
onChanged: (text) {
// Escuchar cambios de texto
print('Entrada actual: $text');
},
),
const SizedBox(height: 20),
// Mostrar el texto ingresado
Text('Has ingresado: $_displayText'),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () {
// Leer texto
setState(() {
_displayText = _controller.text;
});
},
child: const Text('Mostrar entrada'),
),
ElevatedButton(
onPressed: () {
// Vaciar texto
_controller.clear();
},
child: const Text('Vaciar'),
),
ElevatedButton(
onPressed: () {
// Establecer texto
_controller.text = 'Texto preestablecido';
},
child: const Text('Establecer texto'),
),
],
);
}
}
const TextFieldExample({super.key});
@override
State<TextFieldExample> createState() => _TextFieldExampleState();
}
class _TextFieldExampleState extends State<TextFieldExample> {
// Crear controlador
final TextEditingController _controller = TextEditingController();
String _displayText = '';
@override
void dispose() {
// Destruir controlador
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Column(
children: [
TextField(
controller: _controller, // Vincular controlador
decoration: const InputDecoration(
labelText: 'Ingresar texto',
),
onChanged: (text) {
// Escuchar cambios de texto
print('Entrada actual: $text');
},
),
const SizedBox(height: 20),
// Mostrar el texto ingresado
Text('Has ingresado: $_displayText'),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () {
// Leer texto
setState(() {
_displayText = _controller.text;
});
},
child: const Text('Mostrar entrada'),
),
ElevatedButton(
onPressed: () {
// Vaciar texto
_controller.clear();
},
child: const Text('Vaciar'),
),
ElevatedButton(
onPressed: () {
// Establecer texto
_controller.text = 'Texto preestablecido';
},
child: const Text('Establecer texto'),
),
],
);
}
}
Control de foco
Usando FocusNode se puede controlar el foco del campo de entrada.
Ejemplo: Control de foco
class FocusExample extends StatefulWidget {
const FocusExample({super.key});
@override
State<FocusExample> createState() => _FocusExampleState();
}
class _FocusExampleState extends State<FocusExample> {
final FocusNode _focusNode1 = FocusNode();
final FocusNode _focusNode2 = FocusNode();
@override
void dispose() {
_focusNode1.dispose();
_focusNode2.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Column(
children: [
TextField(
focusNode: _focusNode1,
decoration: const InputDecoration(labelText: 'Campo de entrada 1'),
),
const SizedBox(height: 10),
TextField(
focusNode: _focusNode2,
decoration: const InputDecoration(labelText: 'Campo de entrada 2'),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () {
// Enfocar el campo de entrada 1
_focusNode1.requestFocus();
},
child: const Text('Enfocar campo de entrada 1'),
),
ElevatedButton(
onPressed: () {
// Enfocar el campo de entrada 2
_focusNode2.requestFocus();
},
child: const Text('Enfocar campo de entrada 2'),
),
ElevatedButton(
onPressed: () {
// Quitar el foco
_focusNode1.unfocus();
_focusNode2.unfocus();
},
child: const Text('Quitar foco'),
),
],
);
}
}
const FocusExample({super.key});
@override
State<FocusExample> createState() => _FocusExampleState();
}
class _FocusExampleState extends State<FocusExample> {
final FocusNode _focusNode1 = FocusNode();
final FocusNode _focusNode2 = FocusNode();
@override
void dispose() {
_focusNode1.dispose();
_focusNode2.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Column(
children: [
TextField(
focusNode: _focusNode1,
decoration: const InputDecoration(labelText: 'Campo de entrada 1'),
),
const SizedBox(height: 10),
TextField(
focusNode: _focusNode2,
decoration: const InputDecoration(labelText: 'Campo de entrada 2'),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () {
// Enfocar el campo de entrada 1
_focusNode1.requestFocus();
},
child: const Text('Enfocar campo de entrada 1'),
),
ElevatedButton(
onPressed: () {
// Enfocar el campo de entrada 2
_focusNode2.requestFocus();
},
child: const Text('Enfocar campo de entrada 2'),
),
ElevatedButton(
onPressed: () {
// Quitar el foco
_focusNode1.unfocus();
_focusNode2.unfocus();
},
child: const Text('Quitar foco'),
),
],
);
}
}
Botones y eventos de clic
Flutter proporciona varios componentes de botón para manejar los clics del usuario.
Ejemplo: Varios botones
// TextButton - Botón de texto
TextButton(
onPressed: () => print('Se hizo clic en el botón de texto'),
child: const Text('Botón de texto'),
)
// ElevatedButton - Botón elevado
ElevatedButton(
onPressed: () => print('Se hizo clic en el botón elevado'),
child: const Text('Enviar'),
)
// OutlinedButton - Botón con contorno
OutlinedButton(
onPressed: () => print('Se hizo clic en el botón con contorno'),
child: const Text('Cancelar'),
)
// IconButton - Botón de icono
IconButton(
icon: const Icon(Icons.favorite),
onPressed: () => print('Se hizo clic en el botón de icono'),
)
// Botón con icono
ElevatedButton.icon(
onPressed: () => print('Se hizo clic en el botón con icono'),
icon: const Icon(Icons.save),
label: const Text('Guardar'),
)
// CupertinoButton - Botón estilo iOS
CupertinoButton(
child: const Text('Botón iOS'),
onPressed: () {},
)
TextButton(
onPressed: () => print('Se hizo clic en el botón de texto'),
child: const Text('Botón de texto'),
)
// ElevatedButton - Botón elevado
ElevatedButton(
onPressed: () => print('Se hizo clic en el botón elevado'),
child: const Text('Enviar'),
)
// OutlinedButton - Botón con contorno
OutlinedButton(
onPressed: () => print('Se hizo clic en el botón con contorno'),
child: const Text('Cancelar'),
)
// IconButton - Botón de icono
IconButton(
icon: const Icon(Icons.favorite),
onPressed: () => print('Se hizo clic en el botón de icono'),
)
// Botón con icono
ElevatedButton.icon(
onPressed: () => print('Se hizo clic en el botón con icono'),
icon: const Icon(Icons.save),
label: const Text('Guardar'),
)
// CupertinoButton - Botón estilo iOS
CupertinoButton(
child: const Text('Botón iOS'),
onPressed: () {},
)
Switch、Checkbox、Radio
Ejemplo: Interruptor, casilla de verificación, botón de opción
class SwitchCheckboxExample extends StatefulWidget {
const SwitchCheckboxExample({super.key});
@override
State<SwitchCheckboxExample> createState() => _SwitchCheckboxExampleState();
}
class _SwitchCheckboxExampleState extends State<SwitchCheckboxExample> {
bool _switchValue = false;
bool _checkboxValue = false;
String _radioValue = 'A';
@override
Widget build(BuildContext context) {
return Column(
children: [
// Switch - Interruptor
Switch(
value: _switchValue,
onChanged: (value) {
setState(() {
_switchValue = value;
});
},
),
Text('Valor de Switch: $_switchValue'),
// Checkbox - Casilla de verificación
Checkbox(
value: _checkboxValue,
onChanged: (value) {
setState(() {
_checkboxValue = value ?? false;
});
},
),
Text('Valor de Checkbox: $_checkboxValue'),
// Radio - Botón de opción
Row(
children: [
Radio<String>(
value: 'A',
groupValue: _radioValue,
onChanged: (value) {
setState(() {
_radioValue = value!;
});
},
),
const Text('Opción A'),
Radio<String>(
value: 'B',
groupValue: _radioValue,
onChanged: (value) {
setState(() {
_radioValue = value!;
});
},
),
const Text('Opción B'),
],
),
Text('Valor de Radio: $_radioValue'),
],
);
}
}
const SwitchCheckboxExample({super.key});
@override
State<SwitchCheckboxExample> createState() => _SwitchCheckboxExampleState();
}
class _SwitchCheckboxExampleState extends State<SwitchCheckboxExample> {
bool _switchValue = false;
bool _checkboxValue = false;
String _radioValue = 'A';
@override
Widget build(BuildContext context) {
return Column(
children: [
// Switch - Interruptor
Switch(
value: _switchValue,
onChanged: (value) {
setState(() {
_switchValue = value;
});
},
),
Text('Valor de Switch: $_switchValue'),
// Checkbox - Casilla de verificación
Checkbox(
value: _checkboxValue,
onChanged: (value) {
setState(() {
_checkboxValue = value ?? false;
});
},
),
Text('Valor de Checkbox: $_checkboxValue'),
// Radio - Botón de opción
Row(
children: [
Radio<String>(
value: 'A',
groupValue: _radioValue,
onChanged: (value) {
setState(() {
_radioValue = value!;
});
},
),
const Text('Opción A'),
Radio<String>(
value: 'B',
groupValue: _radioValue,
onChanged: (value) {
setState(() {
_radioValue = value!;
});
},
),
const Text('Opción B'),
],
),
Text('Valor de Radio: $_radioValue'),
],
);
}
}
Slider - Control deslizante
Ejemplo: Uso de Slider
class SliderExample extends StatefulWidget {
const SliderExample({super.key});
@override
State<SliderExample> createState() => _SliderExampleState();
}
class _SliderExampleState extends State<SliderExample> {
double _sliderValue = 0.5;
@override
Widget build(BuildContext context) {
return Column(
children: [
Slider(
value: _sliderValue, // Valor actual (0.0-1.0)
min: 0.0,
max: 1.0,
divisions: 10, // Dividido en 10 marcas
label: '${(_sliderValue * 100).round()}%',
onChanged: (value) {
setState(() {
_sliderValue = value;
});
},
),
Text('Valor actual: ${(_sliderValue * 100).round()}%'),
// Control deslizante de rango
RangeSlider(
values: const RangeValues(0.3, 0.7),
min: 0.0,
max: 1.0,
onChanged: (values) {
print('Rango: ${values.start} - ${values.end}');
},
),
],
);
}
}
const SliderExample({super.key});
@override
State<SliderExample> createState() => _SliderExampleState();
}
class _SliderExampleState extends State<SliderExample> {
double _sliderValue = 0.5;
@override
Widget build(BuildContext context) {
return Column(
children: [
Slider(
value: _sliderValue, // Valor actual (0.0-1.0)
min: 0.0,
max: 1.0,
divisions: 10, // Dividido en 10 marcas
label: '${(_sliderValue * 100).round()}%',
onChanged: (value) {
setState(() {
_sliderValue = value;
});
},
),
Text('Valor actual: ${(_sliderValue * 100).round()}%'),
// Control deslizante de rango
RangeSlider(
values: const RangeValues(0.3, 0.7),
min: 0.0,
max: 1.0,
onChanged: (values) {
print('Rango: ${values.start} - ${values.end}');
},
),
],
);
}
}
Otras extensionesAl manejar la entrada de usuario, recuerde usar setState para actualizar el estado de la interfaz, para que la interfaz responda a las acciones del usuario.