Diferencia entre revisiones de «Flutter Diálogos»
Ir a la navegación
Ir a la búsqueda
| (No se muestran 6 ediciones intermedias del mismo usuario) | |||
| Línea 7: | Línea 7: | ||
| − | * Creamos una nueva página en la [https://wiki.cifprodolfoucha.es/index.php?title=Flutter_Widget#Estructura_de_p.C3.A1ginas carpeta pages] de nombre ''' | + | * Creamos una nueva página en la [https://wiki.cifprodolfoucha.es/index.php?title=Flutter_Widget#Estructura_de_p.C3.A1ginas carpeta pages] de nombre '''dialogos_page.dart''' |
: En todas las páginas haremos lo mismo: | : En todas las páginas haremos lo mismo: | ||
:* Importamos la librería de 'material' (recordar que existe un [https://github.com/marius-h/flutter_enhancement_suite/blob/main/SNIPPETS.md#flutter-widget-snippets snippet] que lo hace automático). | :* Importamos la librería de 'material' (recordar que existe un [https://github.com/marius-h/flutter_enhancement_suite/blob/main/SNIPPETS.md#flutter-widget-snippets snippet] que lo hace automático). | ||
| − | :* Creamos una clase que derive de | + | :* Creamos una clase (DialogosPage) que derive de '''StatefulWidget'''. Se creará (si lo hacéis con un Snippet) una clase asociada que deriva de State. |
| − | :* | + | :* Modificamos la clase State y en su métod build hacemos que devuelva un Scaffold con una Appbar (hacerlo con un Snippet) |
| Línea 47: | Línea 47: | ||
<br /> | <br /> | ||
| − | :<syntaxhighlight lang="java" enclose="div" highlight=" | + | :<syntaxhighlight lang="java" enclose="div" highlight="14,23-46" > |
import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||
| − | class | + | class DialogosPage extends StatelessWidget { |
@override | @override | ||
| Línea 58: | Línea 58: | ||
title: Text('Ejemplos de Alert'), | title: Text('Ejemplos de Alert'), | ||
), | ), | ||
| − | body: | + | body: ListView( |
| − | |||
children: [ | children: [ | ||
| − | + | TextButton( | |
| − | + | onPressed: () => _mostrarAlerta1(context).then((value) => print(value)), // El then no es obligatorio. Lo pondríamos si queremos recibir información de vuelta | |
| − | + | child: Text('Alerta 1',style: TextStyle(color: Colors.yellow),), | |
| − | + | style: ElevatedButton.styleFrom(primary: Colors.blue,shape: StadiumBorder()) | |
| − | + | ) | |
| − | + | ], | |
| − | + | ), | |
); | ); | ||
} | } | ||
| − | Future _mostrarAlerta1(BuildContext context){ | + | Future _mostrarAlerta1(BuildContext context){ |
return showDialog(context: context, | return showDialog(context: context, | ||
builder: (BuildContext context) { | builder: (BuildContext context) { | ||
| Línea 98: | Línea 97: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
| + | |||
| + | |||
| + | |||
| + | <br /> | ||
| + | ===AlertDialog con un TextField=== | ||
| + | |||
| + | * En este ejemplo muestro como emplear un ShowDIalog en el que en su interior aparece un TextField donde recogemos alguna información. | ||
| + | : El Widget principal es un StatefulWidget ya que quiero mostrar gráficamente el texto introducido en el diálogo, pero esto no tiene por que ser necesario. | ||
| + | :<syntaxhighlight lang="java" enclose="div" highlight="19,31-50" > | ||
| + | class DialogoConTexto extends StatefulWidget { | ||
| + | |||
| + | DialogoConTexto({Key? key}) : super(key: key); | ||
| + | |||
| + | @override | ||
| + | State<DialogoConTexto> createState() => _DialogoConTextoState(); | ||
| + | } | ||
| + | |||
| + | class _DialogoConTextoState extends State<DialogoConTexto> { | ||
| + | var textoAMostrar = ''; | ||
| + | |||
| + | @override | ||
| + | Widget build(BuildContext context) { | ||
| + | return Column( | ||
| + | children: [ | ||
| + | Text('Texto recogido del Alert Dialogo:$textoAMostrar'), | ||
| + | ElevatedButton( | ||
| + | onPressed: () async { | ||
| + | String? textoDeVuelta = await mostrarDialogo(context); | ||
| + | print(textoDeVuelta); // Podríamos no usar un stateful e trabajar sobre la variable | ||
| + | setState(() { | ||
| + | textoAMostrar = textoDeVuelta ?? ''; | ||
| + | }); | ||
| + | }, | ||
| + | child: Text('Mostrar Dialogo') | ||
| + | ), | ||
| + | ], | ||
| + | ); | ||
| + | } | ||
| + | |||
| + | Future<String?>mostrarDialogo(BuildContext context) async { | ||
| + | var texto = ''; // Texto escrito | ||
| + | |||
| + | return showDialog<String>( | ||
| + | context: context, | ||
| + | builder: ( context ) => AlertDialog( | ||
| + | title: Text('Recogiendo informacion'), | ||
| + | content: TextField( | ||
| + | onChanged: (valor) => texto = valor , | ||
| + | decoration: InputDecoration(hintText: 'Texto en diálogo'), | ||
| + | ), | ||
| + | actions: [ | ||
| + | TextButton( | ||
| + | onPressed: () => Navigator.of(context).pop(texto), child: Text('OK') // En el pop mando el texto | ||
| + | ) | ||
| + | ], | ||
| + | ) | ||
| + | ); | ||
| + | |||
| + | } | ||
| + | } | ||
| + | |||
| + | </syntaxhighlight> | ||
| + | |||
| + | :* '''Línea 19:''' Fijarse que el diálogo devuelve un Future del tipo de dato que se lee en la caja de texto, en el ejemplo un String. | ||
| Línea 111: | Línea 174: | ||
:* https://api.flutter.dev/flutter/material/TimePickerDialog-class.html | :* https://api.flutter.dev/flutter/material/TimePickerDialog-class.html | ||
:* https://api.flutter.dev/flutter/material/showTimePicker.html | :* https://api.flutter.dev/flutter/material/showTimePicker.html | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| Línea 140: | Línea 195: | ||
* En el ejemplo aparecen dos cajas de texto que al pulsar encima de ellas, en una aparece la ventana modal para seleccionar una fecha y en el otro para seleccionar un hora-minuto. | * En el ejemplo aparecen dos cajas de texto que al pulsar encima de ellas, en una aparece la ventana modal para seleccionar una fecha y en el otro para seleccionar un hora-minuto. | ||
| − | [[Imagen: | + | [[Imagen:Flutter_dart_dialogos_2.JPG|300px|center]] |
| − | :<syntaxhighlight lang="java" enclose="div" highlight=" | + | :<syntaxhighlight lang="java" enclose="div" highlight="19,59-157" > |
| + | import 'package:flutter/material.dart'; | ||
import 'package:intl/intl.dart'; | import 'package:intl/intl.dart'; | ||
| − | |||
| − | |||
| − | class | + | class DialogosPage extends StatelessWidget { |
| − | |||
@override | @override | ||
| − | + | Widget build(BuildContext context) { | |
| + | return Scaffold( | ||
| + | appBar: AppBar( | ||
| + | title: Text('Ejemplos de Alert'), | ||
| + | ), | ||
| + | body: ListView( | ||
| + | children: [ | ||
| + | TextButton( | ||
| + | onPressed: () => _mostrarAlerta1(context).then((value) => print(value)), // El then no es obligatorio. Lo pondríamos si queremos recibir información de vuelta | ||
| + | child: Text('Alerta 1',style: TextStyle(color: Colors.yellow),), | ||
| + | style: ElevatedButton.styleFrom(primary: Colors.blue,shape: StadiumBorder()) | ||
| + | ), | ||
| + | _MostrarDateTimePicker(), | ||
| + | ], | ||
| + | ), | ||
| + | ); | ||
| + | } | ||
| + | |||
| + | Future _mostrarAlerta1(BuildContext context){ | ||
| + | return showDialog(context: context, | ||
| + | builder: (BuildContext context) { | ||
| + | return AlertDialog( | ||
| + | title: Text('Título del diálogo'), | ||
| + | content: Column( | ||
| + | mainAxisSize: MainAxisSize.min, // Para que la columna no ocupe todo el alto de la pantalla | ||
| + | children: [ | ||
| + | Text('Contenido del diálogo. Texto que queramos que aparezca para informar al usuario de algo'), | ||
| + | FlutterLogo(size: 50,) | ||
| + | ], | ||
| + | ), | ||
| + | actions: [ | ||
| + | TextButton(onPressed: () => Navigator.pop(context), child: Text('Cancelar')), // Cerramos el diálogo | ||
| + | TextButton(onPressed: (){ | ||
| + | // Pondríamos el código que queramos | ||
| + | Navigator.pop(context,'Valor de vuelta'); // Envío de vuelta a quien llamó la información que quiera. NO ES OBLIGATORIO | ||
| + | }, child: Text('Aceptar')), | ||
| + | |||
| + | ], | ||
| + | );; | ||
| + | }, | ||
| + | ); | ||
| + | } | ||
| + | |||
| + | |||
} | } | ||
| + | class _MostrarDateTimePicker extends StatefulWidget { | ||
| + | const _MostrarDateTimePicker({Key? key}) : super(key: key); | ||
| + | @override | ||
| + | _MostrarDateTimePickerState createState() => _MostrarDateTimePickerState(); | ||
| + | } | ||
| − | class | + | class _MostrarDateTimePickerState extends State<_MostrarDateTimePicker> { |
| − | |||
| − | |||
| − | |||
String _fechaEscojida = ''; | String _fechaEscojida = ''; | ||
String _horaEscojida = ''; | String _horaEscojida = ''; | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
TextEditingController _inputFieldDateController = new TextEditingController(); | TextEditingController _inputFieldDateController = new TextEditingController(); | ||
| Línea 176: | Línea 267: | ||
@override | @override | ||
Widget build(BuildContext context) { | Widget build(BuildContext context) { | ||
| − | return | + | return Column( |
| − | + | children: [ | |
| − | + | Divider(), | |
| − | + | _DatePickerTimePicker(), | |
| − | + | Divider(), | |
| − | + | Divider(), | |
| − | + | _visualizarDatos(), | |
| − | + | ] | |
| − | + | ); | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
} | } | ||
| Línea 209: | Línea 281: | ||
return Column( | return Column( | ||
children: [ | children: [ | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
Text('Fecha escojida: $_fechaEscojida'), | Text('Fecha escojida: $_fechaEscojida'), | ||
Text('Hora escojida: $_horaEscojida'), | Text('Hora escojida: $_horaEscojida'), | ||
| Línea 223: | Línea 288: | ||
Widget _DatePickerTimePicker(){ | Widget _DatePickerTimePicker(){ | ||
| − | |||
return | return | ||
| − | + | Column( | |
| − | + | children: [ | |
| − | + | TextField( | |
| − | + | controller: _inputFieldDateController, | |
| − | + | decoration: InputDecoration( | |
| − | + | hintText: 'Fecha de ingreso', | |
| − | + | labelText: 'Fecha de ingreso', | |
| − | + | suffixIcon: Icon(Icons.date_range), | |
| − | + | border: OutlineInputBorder( | |
| − | + | borderRadius: BorderRadius.circular(15.0), | |
| − | + | ) | |
| − | |||
| − | |||
| − | |||
), | ), | ||
| − | SizedBox(height: 10.0,), | + | readOnly: true, |
| − | + | onTap: () => _mostrarDatePicker(), | |
| − | + | ), | |
| − | + | SizedBox(height: 10.0,), | |
| − | + | TextField( | |
| − | + | controller: _inputFieldTimeController, | |
| − | + | decoration: InputDecoration( | |
| − | + | hintText: 'Hora de ingreso', | |
| − | + | labelText: 'Hora de ingreso', | |
| − | + | suffixIcon: Icon(Icons.timelapse), | |
| − | + | border: OutlineInputBorder( | |
| − | + | borderRadius: BorderRadius.circular(15.0), | |
| − | + | ) | |
), | ), | ||
| + | readOnly: true, | ||
| + | onTap: () => _mostrarTimePicker(), | ||
| + | ), | ||
| − | + | ], | |
| − | + | ); | |
} | } | ||
| Línea 264: | Línea 328: | ||
showDatePicker(context: context, initialDate: DateTime.now(), firstDate: DateTime(1995),lastDate: DateTime(2024), | showDatePicker(context: context, initialDate: DateTime.now(), firstDate: DateTime(1995),lastDate: DateTime(2024), | ||
helpText: 'Fecha de ingreso') | helpText: 'Fecha de ingreso') | ||
| − | + | .then((value){ | |
| − | + | setState(() { // Necesitamos redibujar el texto para que muestre la fecha | |
| − | + | if (value !=null) { | |
| − | + | _fechaEscojida = DateFormat('dd-MM-yyyy').format(value); | |
| − | + | _inputFieldDateController.text = _fechaEscojida; | |
| − | + | } | |
| − | } | ||
}); | }); | ||
| + | }); | ||
} | } | ||
| Línea 291: | Línea 355: | ||
}); | }); | ||
} | } | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
} | } | ||
| Línea 439: | Línea 360: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
| + | '''<u>Explicaciones:</u>''' | ||
| + | :* '''Línea 52:''' Creo un StateFulWidget ya que necesitamos actualizar las dos cajas de texto con la fecha-hora seleccionada. | ||
| + | :* '''Línea 60-61:''' Defino las variables que van a guardar la fecha-hora seleccionada y que van a visualizar las dos cajas de texto. | ||
| + | :* '''Línea 64-65:''' Creo dos TextEditingController para poder modificar el texto de las dos cajas de texto. | ||
| + | :* '''Línea 104-108:''' Gestionamos el método onTap de las dos cajas de texto (TextField) para lanzar el diálogo que muestra la fecha/hora a escojer. | ||
| + | :* '''Línea 126-138:''' Método _mostrarDatePicker. Visualiza un DatePicker. | ||
| + | :* '''Línea 148-156:''' Método _mostrarTimePicker. Visualiza un TimePicker. | ||
| + | |||
* <u>'''NOTA:</u>''' Si quieréis hacer que el DatePicker y TimePicker estén en español, seguir [https://wiki.cifprodolfoucha.es/index.php?title=Flutter_Internacionalizaci%C3%B3n lo indicado en este enlace de la Wiki] | * <u>'''NOTA:</u>''' Si quieréis hacer que el DatePicker y TimePicker estén en español, seguir [https://wiki.cifprodolfoucha.es/index.php?title=Flutter_Internacionalizaci%C3%B3n lo indicado en este enlace de la Wiki] | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
Revisión actual del 16:59 11 dic 2022
Intruducción
- Los díalogos suelen ser ventanas modales (no se puede iteraccionar con la aplicación hasta que se cierre) en los que:
- Se informa de algo
- Se solicita información al usuario.
- Creamos una nueva página en la carpeta pages de nombre dialogos_page.dart
- En todas las páginas haremos lo mismo:
- Importamos la librería de 'material' (recordar que existe un snippet que lo hace automático).
- Creamos una clase (DialogosPage) que derive de StatefulWidget. Se creará (si lo hacéis con un Snippet) una clase asociada que deriva de State.
- Modificamos la clase State y en su métod build hacemos que devuelva un Scaffold con una Appbar (hacerlo con un Snippet)
AlertDialog
- Más información en https://api.flutter.dev/flutter/material/AlertDialog-class.html
- En este tipo de diálogo vais a tener que 'mostrarlo'. Para ello vamos a hacer uso de la clase showDialog a la que vamos a tener que:
- Enviar en forma de parámetro el buildcontext.
- Devolver el Widget que queremos que se visualice como 'contenido' del diálogo. Esto lo indicamos en el parámetro builder.
- barrierDismissible: Indicamos si queremos que se pueda cerrar el diálogo al pulsar fuera del mismo (por defecto es true).
- Al instanciar esta clase, se devuelve un Future. En dicho Future puede venir información sobre qué opción fue pulsada por parte del usuario (al cerrar al diálogo con el método pop de la clase Navigator, se puede enviar información de vuelta a quien llamó al showDialog).
- Este tipo de diálogos suelen ser empleados para informar al usuario de algo o para que escoga entre un número limitado de opciones (normalmente dos) la acción a seguir.
- Los parámetros más importantes son:
- title: Título de la alerta.
- content: Contenido de la alerta.
- actions: Lista de widget que van a conformar las 'acciones' que va a tener el alertdialog. Normalmente son botones.
- Para cerrar el diálogo podemos hacer uso del método pop de la clase Navigator.
- Veamos un ejemplo:
import 'package:flutter/material.dart'; class DialogosPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Ejemplos de Alert'), ), body: ListView( children: [ TextButton( onPressed: () => _mostrarAlerta1(context).then((value) => print(value)), // El then no es obligatorio. Lo pondríamos si queremos recibir información de vuelta child: Text('Alerta 1',style: TextStyle(color: Colors.yellow),), style: ElevatedButton.styleFrom(primary: Colors.blue,shape: StadiumBorder()) ) ], ), ); } Future _mostrarAlerta1(BuildContext context){ return showDialog(context: context, builder: (BuildContext context) { return AlertDialog( title: Text('Título del diálogo'), content: Column( mainAxisSize: MainAxisSize.min, // Para que la columna no ocupe todo el alto de la pantalla children: [ Text('Contenido del diálogo. Texto que queramos que aparezca para informar al usuario de algo'), FlutterLogo(size: 50,) ], ), actions: [ TextButton(onPressed: () => Navigator.pop(context), child: Text('Cancelar')), // Cerramos el diálogo TextButton(onPressed: (){ // Pondríamos el código que queramos Navigator.pop(context,'Valor de vuelta'); // Envío de vuelta a quien llamó la información que quiera. NO ES OBLIGATORIO }, child: Text('Aceptar')), ], );; }, ); } }
AlertDialog con un TextField
- En este ejemplo muestro como emplear un ShowDIalog en el que en su interior aparece un TextField donde recogemos alguna información.
- El Widget principal es un StatefulWidget ya que quiero mostrar gráficamente el texto introducido en el diálogo, pero esto no tiene por que ser necesario.
class DialogoConTexto extends StatefulWidget { DialogoConTexto({Key? key}) : super(key: key); @override State<DialogoConTexto> createState() => _DialogoConTextoState(); } class _DialogoConTextoState extends State<DialogoConTexto> { var textoAMostrar = ''; @override Widget build(BuildContext context) { return Column( children: [ Text('Texto recogido del Alert Dialogo:$textoAMostrar'), ElevatedButton( onPressed: () async { String? textoDeVuelta = await mostrarDialogo(context); print(textoDeVuelta); // Podríamos no usar un stateful e trabajar sobre la variable setState(() { textoAMostrar = textoDeVuelta ?? ''; }); }, child: Text('Mostrar Dialogo') ), ], ); } Future<String?>mostrarDialogo(BuildContext context) async { var texto = ''; // Texto escrito return showDialog<String>( context: context, builder: ( context ) => AlertDialog( title: Text('Recogiendo informacion'), content: TextField( onChanged: (valor) => texto = valor , decoration: InputDecoration(hintText: 'Texto en diálogo'), ), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(texto), child: Text('OK') // En el pop mando el texto ) ], ) ); } }
- Línea 19: Fijarse que el diálogo devuelve un Future del tipo de dato que se lee en la caja de texto, en el ejemplo un String.
DatePicker / TimePicker
- Más información:
- Estos dos elementos gráficos muestran una ventana modal con controles gráficos para escojer una fecha / hora según el caso.
- Normalmente se muestra al usuario un TextField inhabilitado (con el parámetro readonly a true o el parámetro enableInteractiveSelection a false) y al pulsar sobre el mismo se muestra la ventana modal para que escoja la fecha / hora. Una vez escojida, se cierra la ventana modal y se muestra la fecha / hora en la caja de texto.
- El tipo de dato que vamos a recoger de la ventana modal del DatePickerDialog va a ser un objeto de la clase DateTime.
- Este devuelve la fecha-hora conjuntamente. Como para cada control vamos a querer mostrar sólo la fecha o sólo la hora, podemos hacer uso del paquete intl el cual nos permite extraer parte del DateTime (lo que nos interese) y guardarlo en forma de String. Para instalarlo debéis seguir los pasos indicados en la pestaña de instalación.
- El tipo de dato que vamos a recoger de la ventana modal del TimePickerDialog va a ser un TimeOfDay. Vamos a necesitar crear un DateTime con la hora-minuto recojida de este control y aplicar la función DateFormat del paquete anterior para mostrar sólo la hora y el minuto.
- En este caso, cuando volvemos de seleccionar una fecha - hora con la ventana modal, recojeremos el resultado de la selección, pero necesitamos modificar el contenido de las cajas de texto donde van a ir esos datos.
- Para hacerlo necesitamos:
- Crear un objeto de la clase TextEditingController (un objeto para cada caja que queramos modificar su contenido, en este ejemplo dos, uno para la hora y otro para la fecha.
- Asociar dicho controlador a cada una de las cajas de texto. Esto se consigue en el parámetro del constructor controller del TextField.
- Desde el método que nos devuelve el resultado de escojer la fecha / hora podemos modificar el contenido con la propiedad text del controlador.
- En el ejemplo aparecen dos cajas de texto que al pulsar encima de ellas, en una aparece la ventana modal para seleccionar una fecha y en el otro para seleccionar un hora-minuto.
import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; class DialogosPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Ejemplos de Alert'), ), body: ListView( children: [ TextButton( onPressed: () => _mostrarAlerta1(context).then((value) => print(value)), // El then no es obligatorio. Lo pondríamos si queremos recibir información de vuelta child: Text('Alerta 1',style: TextStyle(color: Colors.yellow),), style: ElevatedButton.styleFrom(primary: Colors.blue,shape: StadiumBorder()) ), _MostrarDateTimePicker(), ], ), ); } Future _mostrarAlerta1(BuildContext context){ return showDialog(context: context, builder: (BuildContext context) { return AlertDialog( title: Text('Título del diálogo'), content: Column( mainAxisSize: MainAxisSize.min, // Para que la columna no ocupe todo el alto de la pantalla children: [ Text('Contenido del diálogo. Texto que queramos que aparezca para informar al usuario de algo'), FlutterLogo(size: 50,) ], ), actions: [ TextButton(onPressed: () => Navigator.pop(context), child: Text('Cancelar')), // Cerramos el diálogo TextButton(onPressed: (){ // Pondríamos el código que queramos Navigator.pop(context,'Valor de vuelta'); // Envío de vuelta a quien llamó la información que quiera. NO ES OBLIGATORIO }, child: Text('Aceptar')), ], );; }, ); } } class _MostrarDateTimePicker extends StatefulWidget { const _MostrarDateTimePicker({Key? key}) : super(key: key); @override _MostrarDateTimePickerState createState() => _MostrarDateTimePickerState(); } class _MostrarDateTimePickerState extends State<_MostrarDateTimePicker> { String _fechaEscojida = ''; String _horaEscojida = ''; TextEditingController _inputFieldDateController = new TextEditingController(); TextEditingController _inputFieldTimeController = new TextEditingController(); @override Widget build(BuildContext context) { return Column( children: [ Divider(), _DatePickerTimePicker(), Divider(), Divider(), _visualizarDatos(), ] ); } Widget _visualizarDatos(){ return Column( children: [ Text('Fecha escojida: $_fechaEscojida'), Text('Hora escojida: $_horaEscojida'), ], ); } Widget _DatePickerTimePicker(){ return Column( children: [ TextField( controller: _inputFieldDateController, decoration: InputDecoration( hintText: 'Fecha de ingreso', labelText: 'Fecha de ingreso', suffixIcon: Icon(Icons.date_range), border: OutlineInputBorder( borderRadius: BorderRadius.circular(15.0), ) ), readOnly: true, onTap: () => _mostrarDatePicker(), ), SizedBox(height: 10.0,), TextField( controller: _inputFieldTimeController, decoration: InputDecoration( hintText: 'Hora de ingreso', labelText: 'Hora de ingreso', suffixIcon: Icon(Icons.timelapse), border: OutlineInputBorder( borderRadius: BorderRadius.circular(15.0), ) ), readOnly: true, onTap: () => _mostrarTimePicker(), ), ], ); } void _mostrarDatePicker(){ // Podríamos poner async en la definición y llamar con un await para que devuelva un DateTime showDatePicker(context: context, initialDate: DateTime.now(), firstDate: DateTime(1995),lastDate: DateTime(2024), helpText: 'Fecha de ingreso') .then((value){ setState(() { // Necesitamos redibujar el texto para que muestre la fecha if (value !=null) { _fechaEscojida = DateFormat('dd-MM-yyyy').format(value); _inputFieldDateController.text = _fechaEscojida; } }); }); } void _mostrarTimePicker(){ // Podríamos poner async en la definición y llamar con un await para que devuelva un DateTime showTimePicker(context: context, initialTime: TimeOfDay(hour: DateTime.now().hour, minute: DateTime.now().minute), helpText: 'Hora de ingreso') .then((value){ setState(() { // Necesitamos redibujar el texto para que muestre la hora if (value !=null) { // Convertimos el formato TimeOfDay a HH:mm Podríamos crear una función para reutilizar siempre que sea necesario final ahora = DateTime.now(); final dt = new DateTime(ahora.year,ahora.month,ahora.day,value.hour,value.minute); final formato = DateFormat.jm(); // Formato HH:mm AM _horaEscojida = formato.format(dt); _inputFieldTimeController.text = _horaEscojida; } }); }); } }
Explicaciones:
- Línea 52: Creo un StateFulWidget ya que necesitamos actualizar las dos cajas de texto con la fecha-hora seleccionada.
- Línea 60-61: Defino las variables que van a guardar la fecha-hora seleccionada y que van a visualizar las dos cajas de texto.
- Línea 64-65: Creo dos TextEditingController para poder modificar el texto de las dos cajas de texto.
- Línea 104-108: Gestionamos el método onTap de las dos cajas de texto (TextField) para lanzar el diálogo que muestra la fecha/hora a escojer.
- Línea 126-138: Método _mostrarDatePicker. Visualiza un DatePicker.
- Línea 148-156: Método _mostrarTimePicker. Visualiza un TimePicker.
- NOTA: Si quieréis hacer que el DatePicker y TimePicker estén en español, seguir lo indicado en este enlace de la Wiki
Enlace a la página principal de la UD5
Enlace a la página principal del curso
-- Ángel D. Fernández González -- (2021).