Diferencia entre revisiones de «Flutter Diálogos»

De MediaWiki
Ir a la navegación Ir a la búsqueda
 
(No se muestran 9 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 '''alert_pages.dart'''
+
* 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 StatelessWidget (al hacerlo será necesario implementar el método build, ya os da un aviso el Android Studio) de nombre AlertPage.
+
:* Creamos una clase (DialogosPage) que derive de '''StatefulWidget'''. Se creará (si lo hacéis con un Snippet) una clase asociada que deriva de State.
−
:* Dentro del método build, retornamos un widget Scaffold (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).
+
:* Modificamos la clase State y en su métod build hacemos que devuelva un Scaffold con una Appbar (hacerlo con un Snippet)
 +
 
 +
 
 +
 
 +
<br />
 +
 
 +
==AlertDialog==
 +
 
 +
 
 +
* Más información en https://api.flutter.dev/flutter/material/AlertDialog-class.html
  
  
−
* En todos los tipos de diálogos vamos a tener que 'mostrarlo'. Para ello vamos a hacer uso de la [https://api.flutter.dev/flutter/material/showDialog.html clase showDialog] a la que vamos a tener que:
+
* En este tipo de diálogo vais a tener que 'mostrarlo'. Para ello vamos a hacer uso de la [https://api.flutter.dev/flutter/material/showDialog.html clase showDialog] a la que vamos a tener que:
 
:* Enviar en forma de parámetro el '''buildcontext'''.
 
:* 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'''.
 
:* 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).
 
:* 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).
 
:: 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).
  
  
−
<br />
 
−
==AlertDialog==
 
−
 
−
* Más información en https://api.flutter.dev/flutter/material/AlertDialog-class.html
 
  
 
* 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.
 
* 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.
Línea 43: Línea 47:
  
 
<br />
 
<br />
−
:<syntaxhighlight lang="java" enclose="div" highlight="15,25-46" >
+
:<syntaxhighlight lang="java" enclose="div" highlight="14,23-46" >
 
import 'package:flutter/material.dart';
 
import 'package:flutter/material.dart';
  
−
class AlertPage extends StatelessWidget {
+
class DialogosPage extends StatelessWidget {
  
 
   @override
 
   @override
Línea 54: Línea 58:
 
           title: Text('Ejemplos de Alert'),
 
           title: Text('Ejemplos de Alert'),
 
         ),
 
         ),
−
         body: Row (
+
         body: ListView(
−
          mainAxisAlignment:MainAxisAlignment.center,
 
 
           children: [
 
           children: [
−
            TextButton(
+
              TextButton(
−
              onPressed: () => _mostrarAlerta1(context).then((value) => print(value)),    // El then no es obligatorio. Lo pondríamos si queremos recibir información de vuelta
+
                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),),
+
                child: Text('Alerta 1',style: TextStyle(color: Colors.yellow),),
−
              style: ElevatedButton.styleFrom(primary: Colors.blue,shape: StadiumBorder())
+
                style: ElevatedButton.styleFrom(primary: Colors.blue,shape: StadiumBorder())
−
            )
+
              )
−
          ],
+
            ],
−
        )
+
          ),
 
     );
 
     );
 
   }
 
   }
  
−
   Future _mostrarAlerta1(BuildContext context){   // Si no vamos a 'devolver' información podríamos definir el método como void y no hacer el return del showDialog.
+
   Future _mostrarAlerta1(BuildContext context){
 
       return showDialog(context: context,
 
       return showDialog(context: context,
 
                 builder: (BuildContext context) {
 
                 builder: (BuildContext context) {
Línea 94: 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 107: 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
−
 
−
 
−
* 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 '''formulario_page.dart'''
 
−
: 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).
 
−
:* Creamos una clase (FormularioPage) 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 136: 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:Flutter_dart_formulario_9.JPG|300px|center]]
+
[[Imagen:Flutter_dart_dialogos_2.JPG|300px|center]]
  
  
−
:<syntaxhighlight lang="java" enclose="div" highlight="17,18,28,29,54,73-74,79-115,117-129,131-147" >
+
:<syntaxhighlight lang="java" enclose="div" highlight="19,59-157" >
 +
import 'package:flutter/material.dart';
 
import 'package:intl/intl.dart';
 
import 'package:intl/intl.dart';
−
import 'package:flutter/material.dart';
 
−
import 'package:flutter/services.dart';
 
  
−
class FormularioPage extends StatefulWidget {
+
class DialogosPage extends StatelessWidget {
−
  const FormularioPage({Key? key}) : super(key: key);
 
  
 
   @override
 
   @override
−
   _FormularioPageState createState() => _FormularioPageState();
+
   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 _FormularioPageState extends State<FormularioPage> {
+
class _MostrarDateTimePickerState extends State<_MostrarDateTimePicker> {
−
  String _nombre = '';
 
−
  String _email = '';
 
−
  String _password = '';
 
 
   String _fechaEscojida = '';
 
   String _fechaEscojida = '';
 
   String _horaEscojida = '';
 
   String _horaEscojida = '';
  
−
  List<String> _optTipoPaciente = ['Crónico', 'Terminal', 'Observación'];
 
−
  String _valorEscojidoTipoPaciente = 'Crónico';
 
−
 
−
  bool _checkEnfermedadTerminal = false;
 
−
  bool _switchHospitalizado = false;
 
−
  String _radioAtenciomInicial='';
 
−
  Set<String> _valoresRadio = {'Cabecera', 'Uci', 'Urgencias'};
 
  
 
   TextEditingController _inputFieldDateController = new TextEditingController();
 
   TextEditingController _inputFieldDateController = new TextEditingController();
Línea 172: Línea 267:
 
   @override
 
   @override
 
   Widget build(BuildContext context) {
 
   Widget build(BuildContext context) {
−
     return Scaffold(
+
     return Column(
−
        appBar: AppBar(
+
      children: [
−
          title: Text('Formulario'),
+
        Divider(),
−
        ),
+
        _DatePickerTimePicker(),
−
        body: ListView(
+
        Divider(),
−
          padding: EdgeInsets.symmetric(horizontal: 5.0,vertical: 10.0),
+
        Divider(),
−
          children: [
+
        _visualizarDatos(),
−
            _crearInput(),    // TextField con múltiples opciones de decoración
+
      ]
−
            Divider(),
+
    );
−
            _crearEmail(),
 
−
            Divider(),
 
−
            _crearPassword(),
 
−
            Divider(),
 
−
            _crearDropDown(),
 
−
            Divider(),
 
−
            _crearCheckBox(),
 
−
            Divider(),
 
−
            _crearSwitch(),
 
−
            Divider(),
 
−
            _crearRadio(),
 
−
            Divider(),
 
−
            _DatePickerTimePicker(),
 
−
            Divider(),
 
−
            Divider(),
 
−
            _visualizarDatos(),
 
−
 
 
−
          ],
 
−
        ));
 
 
   }
 
   }
  
Línea 205: Línea 281:
 
     return Column(
 
     return Column(
 
       children: [
 
       children: [
−
        Text('Nombre del paciente: $_nombre'),
 
−
        Text('Email del paciente: $_email'),
 
−
        Text('Password: $_password'),
 
−
        Text('Tipo de paciente: $_valorEscojidoTipoPaciente'),
 
−
        Text('Enfermedad terminal: $_checkEnfermedadTerminal'),
 
−
        Text('Hospitalizado: $_switchHospitalizado'),
 
−
        Text('Atendido inicialmente en: $_radioAtenciomInicial'),
 
 
         Text('Fecha escojida: $_fechaEscojida'),
 
         Text('Fecha escojida: $_fechaEscojida'),
 
         Text('Hora escojida: $_horaEscojida'),
 
         Text('Hora escojida: $_horaEscojida'),
Línea 219: Línea 288:
  
 
   Widget _DatePickerTimePicker(){
 
   Widget _DatePickerTimePicker(){
−
 
 
     return
 
     return
−
        Column(
+
      Column(
−
          children: [
+
        children: [
−
            TextField(
+
          TextField(
−
              controller: _inputFieldDateController,
+
            controller: _inputFieldDateController,
−
              decoration: InputDecoration(
+
            decoration: InputDecoration(
−
                  hintText: 'Fecha de ingreso',
+
                hintText: 'Fecha de ingreso',
−
                  labelText: 'Fecha de ingreso',
+
                labelText: 'Fecha de ingreso',
−
                  suffixIcon: Icon(Icons.date_range),
+
                suffixIcon: Icon(Icons.date_range),
−
                  border: OutlineInputBorder(
+
                border: OutlineInputBorder(
−
                    borderRadius: BorderRadius.circular(15.0),
+
                  borderRadius: BorderRadius.circular(15.0),
−
                  )
+
                )
−
              ),
 
−
              readOnly: true,
 
−
              onTap: () => _mostrarDatePicker(),
 
 
             ),
 
             ),
−
             SizedBox(height: 10.0,),
+
             readOnly: true,
−
            TextField(
+
            onTap: () => _mostrarDatePicker(),
−
              controller: _inputFieldTimeController,
+
          ),
−
              decoration: InputDecoration(
+
          SizedBox(height: 10.0,),
−
                  hintText: 'Hora de ingreso',
+
          TextField(
−
                  labelText: 'Hora de ingreso',
+
            controller: _inputFieldTimeController,
−
                  suffixIcon: Icon(Icons.timelapse),
+
            decoration: InputDecoration(
−
                  border: OutlineInputBorder(
+
                hintText: 'Hora de ingreso',
−
                    borderRadius: BorderRadius.circular(15.0),
+
                labelText: 'Hora de ingreso',
−
                  )
+
                suffixIcon: Icon(Icons.timelapse),
−
              ),
+
                border: OutlineInputBorder(
−
              readOnly: true,
+
                  borderRadius: BorderRadius.circular(15.0),
−
              onTap: () => _mostrarTimePicker(),
+
                )
 
             ),
 
             ),
 +
            readOnly: true,
 +
            onTap: () => _mostrarTimePicker(),
 +
          ),
  
−
          ],
+
        ],
−
        );
+
      );
  
 
   }
 
   }
Línea 260: 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){
+
        .then((value){
−
        setState(() {  // Necesitamos redibujar el texto para que muestre la fecha
+
      setState(() {  // Necesitamos redibujar el texto para que muestre la fecha
−
          if (value !=null) {
+
        if (value !=null) {
−
            _fechaEscojida = DateFormat('dd-MM-yyyy').format(value);
+
          _fechaEscojida = DateFormat('dd-MM-yyyy').format(value);
−
            _inputFieldDateController.text = _fechaEscojida;
+
          _inputFieldDateController.text = _fechaEscojida;
−
          }
+
         }
−
         });
 
 
       });
 
       });
 +
    });
 
   }
 
   }
  
Línea 287: Línea 355:
 
     });
 
     });
 
   }
 
   }
−
 
−
  Widget _crearRadio(){
 
−
 
−
    return Column(
 
−
      mainAxisAlignment: MainAxisAlignment.center,
 
−
      children: _elemsRadio(),
 
−
    ) ;
 
−
  }
 
−
 
−
  List<Widget>_elemsRadio(){
 
−
    List<Widget> lista = [];
 
−
    _valoresRadio.forEach((element) {
 
−
      RadioListTile r = RadioListTile(
 
−
          title: Text(element),
 
−
          value: element,
 
−
          groupValue: _radioAtenciomInicial,
 
−
          onChanged: (valor){ setState(() {
 
−
            _radioAtenciomInicial = valor;
 
−
          });},
 
−
        );
 
−
        lista.add(r);
 
−
    });
 
−
    return lista;
 
−
  }
 
−
 
−
  Widget _crearSwitch(){
 
−
    return SwitchListTile(
 
−
        title: Text('Hospitalizado'),
 
−
        subtitle: Text('Indica si está hospitalizado'),
 
−
        secondary: Icon(Icons.accessibility),
 
−
        value: _switchHospitalizado,
 
−
        onChanged: (valor) { setState(() {
 
−
          _switchHospitalizado = valor;
 
−
        }); });
 
−
  }
 
−
  Widget _crearCheckBox(){
 
−
    return CheckboxListTile(
 
−
        title: Text('Enfermedad terminal'),
 
−
        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.0),side: BorderSide(color: Colors.grey)),
 
−
        value: _checkEnfermedadTerminal,
 
−
        onChanged: (nuevoValor) {  // Hay que llamar a setState para que redibuje el CheckBox
 
−
          setState(() { _checkEnfermedadTerminal = nuevoValor! ;});
 
−
        }
 
−
 
−
    );
 
−
  }
 
−
  Widget _crearDropDown(){
 
−
    return Container(
 
−
      height: 60.0,
 
−
      padding: EdgeInsets.only(left: 8.0),
 
−
      decoration: BoxDecoration(
 
−
        borderRadius: BorderRadius.circular(15.0),
 
−
        border: Border.all(
 
−
          color: Colors.grey
 
−
        )
 
−
      ),
 
−
      child: Row(
 
−
        children: [
 
−
          DropdownButton(
 
−
            value: _valorEscojidoTipoPaciente,
 
−
            onChanged: (String? valor) { setState(() { _valorEscojidoTipoPaciente = valor!; });},
 
−
            items: _crearItemsDropDown(),
 
−
 
−
          ),
 
−
          Spacer(),
 
−
          Container(child: Icon(Icons.api),
 
−
                    padding: EdgeInsets.only(right: 10.0),
 
−
          ),
 
−
        ],
 
−
      ),
 
−
    );
 
−
  }
 
−
 
−
  List<DropdownMenuItem<String>> _crearItemsDropDown(){
 
−
 
−
    List<DropdownMenuItem<String>> lista = [];
 
−
    _optTipoPaciente.forEach((element) {
 
−
      lista.add(DropdownMenuItem(child: Text('$element'),value: element,));
 
−
    });
 
−
 
−
    return lista;
 
−
  }
 
−
 
−
  Widget _crearEmail(){
 
−
 
−
    return TextField(
 
−
      onChanged: (valor) => setState((){
 
−
                                        _email = valor;
 
−
                                        print(valor);}
 
−
                                    ),  // Fijarse que podemos guardar una cadena vacía
 
−
      keyboardType: TextInputType.emailAddress,
 
−
      decoration: InputDecoration(
 
−
        hintText: 'Email del paciente',
 
−
        labelText: 'Email',
 
−
        suffixIcon: Icon(Icons.email),
 
−
        border: OutlineInputBorder(
 
−
          borderRadius: BorderRadius.circular(15.0),
 
−
        )
 
−
      ),
 
−
    );
 
−
  }
 
−
 
−
 
−
  Widget _crearPassword(){
 
−
 
−
    return TextField(
 
−
      onChanged: (valor) => setState((){_password = valor;}),  // Fijarse que podemos guardar una cadena vacía
 
−
      obscureText: true,
 
−
      obscuringCharacter: '-',
 
−
      maxLength: 20,
 
−
      decoration: InputDecoration(
 
−
          hintText: 'Password de entrada',
 
−
          labelText: 'Password',
 
−
          suffixIcon: Icon(Icons.password),
 
−
          border: OutlineInputBorder(
 
−
            borderRadius: BorderRadius.circular(15.0),
 
−
          )
 
−
      ),
 
−
    );
 
−
  }
 
−
 
−
  Widget _crearInput() {
 
−
 
−
    return TextField(
 
−
      onChanged: (valor) => setState((){_nombre = valor;}),  // Fijarse que podemos guardar una cadena vacía
 
−
      textCapitalization: TextCapitalization.words,
 
−
      keyboardType: TextInputType.name,
 
−
      decoration: InputDecoration(
 
−
        border: OutlineInputBorder(    // Establece un borde cicular/otro  alrededor de la caja de texto
 
−
          borderRadius: BorderRadius.circular(15.0),
 
−
        ),
 
−
        counterText: 'Número de caracteres: ${_nombre.length}',  // Texto que aparece a la derecha y debajo de la caja
 
−
        hintText: 'Nombre del paciente',          // Texto que aparece dentro de la caja y desaparece al escribir
 
−
        labelText: 'Nombre',                      // Texto qye aparece encima de la caja AL PULSAR EN EL INTERIOR PARA ESCRIBIR
 
−
        helperText: 'Introduce el nombre del paciente',  // Texto que aparece a la izquierda y abajo de la caja
 
−
        suffixIcon: Icon(Icons.access_alarm),    // Widget que aparece a la derecha dentro de la caja
 
−
        icon: Icon(Icons.accessibility),          // Widget que aparece a la izquierda fuera de la caja
 
−
 
−
      ),
 
−
    );
 
−
 
−
  }
 
−
 
 
}
 
}
  
Línea 435: 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.
  
 +
  
  
Línea 441: Línea 374:
  
  
−
<br />
 
−
 
−
 
−
 
−
 
−
<br />
 
−
 
−
==TimePickerDialog==
 
  
  

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


  • 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:
Flutter dart alert 1.JPG



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.


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.
Flutter dart dialogos 2.JPG


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.







Enlace a la página principal de la UD5

Enlace a la página principal del curso




-- Ángel D. Fernández González -- (2021).