arrow_back Volver
Inicio keyboard_arrow_right Artículos keyboard_arrow_right Artículo

Formulario con Flutter

Marines Méndez

Software Developer

av_timer 6 Min. de lectura

remove_red_eye 30135 visitas

calendar_today 29 Octubre 2019

Texto alternativo

Para crear nuestro formulario primero vamos a usar la clase TextEditingController con este obtendremos el texto de nuestras cajas, así que vamos a crear nuestras variables e instanciamos con la misma clase:

  TextEditingController  nameCtrl = new TextEditingController();
  TextEditingController  emailCtrl = new TextEditingController();
  TextEditingController  mobileCtrl = new TextEditingController();
  TextEditingController  passwordCtrl = new TextEditingController();
  TextEditingController  repeatPassCtrl = new TextEditingController();

Declaramos otra variable con la clase GlobalKey esta nos servirá para poder manejar nuestro formulario:

GlobalKey<FormState> keyForm= new GlobalKey();

Vamos a crear nuestro widget primero usaremos un SingleChildScrollView ya que si abrimos nuestra aplicación en una pantalla pequeña puede que el usuario no pueda ver todos los elementos y tenga que realizar el scroll para poder ver los demás campos, dentro de este agregar un Container para poder especificar el margen de nuestro formulario y dentro de este agregamos un Form donde agregaremos nuestras cajas de texto y también colocamos nuestra llave que creamos anteriormente:

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text('Registrar'),
        ),
        body: new SingleChildScrollView(
          child: new Container(
            margin: new EdgeInsets.all(20.0),
            child: new Form(
              key: keyForm,
              child: formUI(), //Este metodo lo crearemos mas adelante
            ),
          ),
        ),
      ),
    );
  }

Vamos a crear un método llamado formItemsDesign y tendremos 2 parámetros icon e item en este recibiremos los elementos de nuestro formulario y le aplicaremos este diseño, dentro del método haremos un diseño similar que tendrán todos los elementos del formulario, colocamos Padding para agregar un espacio entre las cajas de texto este será simétrico de manera vertical, también usaremos Card para resaltar las cajas de texto y ListTile para poder colocar iconos en nuestras cajas de textos :

formItemsDesign(icon, item) {
 return Padding(
   padding: EdgeInsets.symmetric(vertical: 7),
   child: Card(child: ListTile(leading: Icon(icon), title: item)),
 );
}

Vamos a crear otro método llamado formUI dentro de este agregaremos Column para colocar todos los elementos del formulario.

Widget formUI() {
    return  Column(
      children: <Widget>[
            //Aqui van los elementos de nuestro dormulario
            ],
    );
        }

Para crear un elemento de nuestro formulatio primero llamamos nuestro método formItemsDesign y dentro de este le agregamos un icono con la clase Icons y seleccionamos el icono ejemplo Icons.person después vamos a usar la clase TextFormField le asignaremos el controlador a cada caja de texto usaremos el método validator para saber si el texto que se encuentra en las cajas es correcto , el codigo quedaria de la siguiente manera en nombre:

formItemsDesign(
   Icons.person,
   TextFormField(
     controller: nameCtrl,
     decoration: new InputDecoration(
       labelText: 'Nombre',
     ),
     validator:,
   )),

formItemsDesign(
   Icons.phone,
   TextFormField(
     controller: mobileCtrl,
       decoration: new InputDecoration(
         labelText: 'Numero de telefono',
       ),
       keyboardType: TextInputType.phone,
       maxLength: 10,
       validator:,)),

formItemsDesign(
   Icons.email,
   TextFormField(
     controller: emailCtrl,
       decoration: new InputDecoration(
         labelText: 'Email',
       ),
       keyboardType: TextInputType.emailAddress,
       maxLength: 32,
       validator: validateEmail,)),

formItemsDesign(
   Icons.remove_red_eye,
   TextFormField(
     controller: passwordCtrl,
     obscureText: true,
     decoration: InputDecoration(
       labelText: 'Contraseña',
     ),
   )),

formItemsDesign(
   Icons.remove_red_eye,
   TextFormField(
     controller: repeatPassCtrl,
     obscureText: true,
     decoration: InputDecoration(
       labelText: 'confirmar Contraseña',
     ),
     validator:,
   ))

Nos marcara error el atributo validator porque no hemos creados las validaciones así que crearemos un método para cada caja de texto excepto la de contraseña ya que solo agregaremos una validación en confirmar contraseña para verificar si las dos contraseñas con iguales las validaciones, quedarían de la siguiente manera:

String validateName(String value) {
 String pattern = r'(^[a-zA-Z ]*$)';
 RegExp regExp = new RegExp(pattern);
 if (value.length == 0) {
   return "El nombre es necesario";
 } else if (!regExp.hasMatch(value)) {
   return "El nombre debe de ser a-z y A-Z";
 }
 return null;
}

String validateMobile(String value) {
 String patttern = r'(^[0-9]*$)';
 RegExp regExp = new RegExp(patttern);
 if (value.length == 0) {
   return "El telefono es necesariod";
 } else if (value.length != 10) {
   return "El numero debe tener 10 digitos";
 }
 return null;
}

String validateEmail(String value) {
 String pattern =
     r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$';
 RegExp regExp = new RegExp(pattern);
 if (value.length == 0) {
   return "El correo es necesario";
 } else if (!regExp.hasMatch(value)) {
   return "Correo invalido";
 } else {
   return null;
 }
}

String validatePassword(String value) {
 print("valorrr $value passsword ${passwordCtrl.text}");
 if (value != passwordCtrl.text) {
   return "Las contraseñas no coinciden";
 }
 return null;
}

Llamamos los métodos dependiendo de la caja de texto en el atributo validate .

Ahora para seleccionar el sexo de la persona usaremos una Columna en donde crearemos dos widget usando la clase RadioListTile en esta aplicaremos el mismo diseño que creamos con el método formItemsDesign si desean pueden agregar un icono sino solo colocamos null:

formItemsDesign(
   null,
   Column(children: <Widget>[
     Text("Género"),

     RadioListTile<String>(
       title: const Text('Hombre'),
       value: 'hombre',
       groupValue: gender,
       onChanged: (value) {
         setState(() {
           gender = value;
         });
       },
     ),

     RadioListTile<String>(
       title: const Text('Mujer'),
       value: 'mujer',
       groupValue: gender,
       onChanged: (value) {
         setState(() {
           gender = value;
         });
       },
     )
   ])),

Creamos un método llamado save que se ejecutará al momento de dar clic sobre un botón que crearemos más adelante, dentro de este vamos a usar nuestra llave keyForm ejectanto el método validate este nos servirá para saber si las validaciones que hicimos anteriormente se realizaron de manera correcta, también usaremos reset para que se borren todos los datos que se encuentran en los campos, este método tienes que llamarlo después de que hayas obtenido los datos de las cajas de texto.

save() {
 if (keyForm.currentState.validate()) {
   print("Nombre ${nameCtrl.text}");
   print("Telefono ${mobileCtrl.text}");
   print("Correo ${emailCtrl.text}");
   keyForm.currentState.reset();
 }
}


Crearemos un botón personalizado usando Container ,LinearGradient y Text para colocar diferentes colores también usaremos el método GestureDetector porque estaremos creando un botón no usaremos un widget especial para esto, así que con esa clase podremos agregarle un clic a nuestro Container y llamaremos el método save :

GestureDetector(
onTap: (){
save(); /*Aquí especificamos que queremos hacer al momento de hacer clic sobre el Container */ 
},child: Container(
     margin: new EdgeInsets.all(30.0),
     alignment: Alignment.center,
     decoration: ShapeDecoration(
       shape: RoundedRectangleBorder(
           borderRadius: BorderRadius.circular(30.0)), /*Aquí agregamos que tan redondeado queremos nuestro button */ 
       gradient: LinearGradient(colors: [
         Color(0xFF0EDED2),
         Color(0xFF03A0FE),
       ],
           begin: Alignment.topLeft, end: Alignment.bottomRight), /* Especificamos en qué parte queremos que se muestre los colores */
     ),
     child: Text("Guardar",
         style: TextStyle(
             color: Colors.white,
             fontSize: 18,
             fontWeight: FontWeight.w500)), 
     padding: EdgeInsets.only(top: 16, bottom: 16),
   ))
 ],
)

Asi nos quedaria el codigo Completo

class RegisterPage extends StatefulWidget {
 @override
 _RegisterPageState createState() => _RegisterPageState();
}

class _RegisterPageState extends State<RegisterPage> {
 GlobalKey<FormState> keyForm = new GlobalKey();
 TextEditingController  nameCtrl = new TextEditingController();
 TextEditingController  emailCtrl = new TextEditingController();
 TextEditingController  mobileCtrl = new TextEditingController();
 TextEditingController  passwordCtrl = new TextEditingController();
 TextEditingController  repeatPassCtrl = new TextEditingController();

 @override
 Widget build(BuildContext context) {
   return MaterialApp(
     home: new Scaffold(
       appBar: new AppBar(
         title: new Text('Registrarse'),
       ),
       body: new SingleChildScrollView(
         child: new Container(
           margin: new EdgeInsets.all(60.0),
           child: new Form(
             key: keyForm,
             child: formUI(),
           ),
         ),
       ),
     ),
   );
 }

 formItemsDesign(icon, item) {
   return Padding(
     padding: EdgeInsets.symmetric(vertical: 7),
     child: Card(child: ListTile(leading: Icon(icon), title: item)),
   );
 }

 String gender = 'hombre';

 Widget formUI() {
   return  Column(
     children: <Widget>[
       formItemsDesign(
           Icons.person,
           TextFormField(
             controller: nameCtrl,
             decoration: new InputDecoration(
               labelText: 'Nombre',
             ),
             validator: validateName,
           )),
       formItemsDesign(
           Icons.phone,
           TextFormField(
             controller: mobileCtrl,
               decoration: new InputDecoration(
                 labelText: 'Numero de telefono',
               ),
               keyboardType: TextInputType.phone,
               maxLength: 10,
               validator: validateMobile,)),
       formItemsDesign(
           null,
           Column(children: <Widget>[
             Text("Genero"),
             RadioListTile<String>(
               title: const Text('Hombre'),
               value: 'hombre',
               groupValue: gender,
               onChanged: (value) {
                 setState(() {
                   gender = value;
                 });
               },
             ),
             RadioListTile<String>(
               title: const Text('Mujer'),
               value: 'mujer',
               groupValue: gender,
               onChanged: (value) {
                 setState(() {
                   gender = value;
                 });
               },
             )
           ])),
       formItemsDesign(
           Icons.email,
           TextFormField(
             controller: emailCtrl,
               decoration: new InputDecoration(
                 labelText: 'Email',
               ),
               keyboardType: TextInputType.emailAddress,
               maxLength: 32,
               validator: validateEmail,)),
       formItemsDesign(
           Icons.remove_red_eye,
           TextFormField(
             controller: passwordCtrl,
             obscureText: true,
             decoration: InputDecoration(
               labelText: 'Contraseña',
             ),
           )),
       formItemsDesign(
           Icons.remove_red_eye,
           TextFormField(
             controller: repeatPassCtrl,
             obscureText: true,
             decoration: InputDecoration(
               labelText: 'Repetir la Contraseña',
             ),
             validator: validatePassword,
           )),
   GestureDetector(
   onTap: (){
     save();
   },child: Container(
         margin: new EdgeInsets.all(30.0),
         alignment: Alignment.center,
         decoration: ShapeDecoration(
           shape: RoundedRectangleBorder(
               borderRadius: BorderRadius.circular(30.0)),
           gradient: LinearGradient(colors: [
             Color(0xFF0EDED2),
             Color(0xFF03A0FE),
           ],
               begin: Alignment.topLeft, end: Alignment.bottomRight),
         ),
         child: Text("Guardar",
             style: TextStyle(
                 color: Colors.white,
                 fontSize: 18,
                 fontWeight: FontWeight.w500)),
         padding: EdgeInsets.only(top: 16, bottom: 16),
       ))
     ],
   );
 }



 String validatePassword(String value) {
   print("valorrr $value passsword ${passwordCtrl.text}");
   if (value != passwordCtrl.text) {
     return "Las contraseñas no coinciden";
   }
   return null;
 }

 String validateName(String value) {
   String pattern = r'(^[a-zA-Z ]*$)';
   RegExp regExp = new RegExp(pattern);
   if (value.length == 0) {
     return "El nombre es necesario";
   } else if (!regExp.hasMatch(value)) {
     return "El nombre debe de ser a-z y A-Z";
   }
   return null;
 }

 String validateMobile(String value) {
   String patttern = r'(^[0-9]*$)';
   RegExp regExp = new RegExp(patttern);
   if (value.length == 0) {
     return "El telefono es necesariod";
   } else if (value.length != 10) {
     return "El numero debe tener 10 digitos";
   }
   return null;
 }

 String validateEmail(String value) {
   String pattern =
       r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$';
   RegExp regExp = new RegExp(pattern);
   if (value.length == 0) {
     return "El correo es necesario";
   } else if (!regExp.hasMatch(value)) {
     return "Correo invalido";
   } else {
     return null;
   }
 }

 save() {
   if (keyForm.currentState.validate()) {
     print("Nombre ${nameCtrl.text}");
     print("Telefono ${mobileCtrl.text}");
     print("Correo ${emailCtrl.text}");
         keyForm.currentState.reset();
   }
 }
}

Aumenta tu productividad con GitHub Copilot

  • done Curso GRATUITO
  • done Regístrate antes del 31 de Marzo
  • done Obtén una ventaja competitiva
  • done Aprovecha la IA a tu favor
Más información