Flutter
- Login com Web API
![]() |
No artigo de hoje veremos como criar uma tela de Login no Flutter e fazer o login usando uma Web API. |
|
O que é o Flutter ?
O Flutter é um SDK de aplicativo móvel do Google que ajuda a criar aplicativos móveis modernos para iOS e Android usando uma única (quase) base de código.
Se você não conhece o Flutter veja o meu artigo : Flutter - Primeiros contatos e impressões
Criando uma interface de Login
Eu já mostrei como criar uma tela de login em outro artigo, por isso neste artigo vou adotar outra abordagem diferente para criar o login.
Vamos começar criando uma tela de login cujo layout pode ser visto abaixo:
![]() |
Destaques da tela de login : - AppBar com título; - Utilização do widget Form; - Dois widgets TextFormField para entrada do usuário com textos; - Nos textos é exibido o teclado numérico; - Um RaisedButton contido em um Container com texto;
|
Criando o projeto : Tela de Login
No Visual
Studio Code tecle CTRL+ SHIFT+P para abrir a
paleta de comandos e a seguir selecione a opção :
Fluter:New Project
A seguir informe o nome do projeto : flutter_login
e tecle ENTER
Na janela de
diálogo a seguir selecione a pasta onde o projeto vai ser salvo e clique em :
Select a folder to create the project in
O Flutter vai criar um projeto padrão onde todo o código da aplicação vai estar no arquivo main.dart dentro da pasta lib do projeto.
Vamos selecionar o arquivo main.dart e apagar todo o código gerado deixando o arquivo vazio.
A pasta lib é a pasta principal para escrever o código do aplicativo. Atualmente, o modelo de projeto padrão contém apenas um arquivo main.dart que é essencialmente um ponto de entrada para o aplicativo Flutter.
A seguir vamos criar dentro da pasta lib outra pasta chamada pages onde vamos criar o widget da nossa tela de login.
Dentro da pasta pages vamos criar o arquivo login_page.dart que representa o widget da nossa tela de login.
Assim, no momento, a estrutura do nosso projeto esta assim:
Definindo a entrada da aplicação no widget StatelessWidget
Na pasta lib vamos abrir o arquivo main.dart,e criar um widget sem estado ou StatelessWidget.
No Visual Studio Code podemos a começar a digitar st , e, poderemos usar a opção do menu de atalho selecionando : Flutter stateless widget
Isso irá gerar o código padrão para criar o widget sem estado. Basta digitar a seguir o nome do widget.
Vamos definir o nome MyApp, incluir a definição do método main() invocando MyApp() e definir a referência ao pacote: flutter/material.dart:
import 'package:flutter_login/pages/login_page.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor : Colors.blue
),
home: LoginPage()
);
}
}
|
Neste código estamos retornando um MaterialApp e definindo os argumentos title, theme e home.
Nota: Veja o meu artigo sobre MaterialApp : Apresentando o widget MaterialApp
No argumento home definimos um novo Widget chamado LoginPage() que será criado no arquivo login_page.dart e por isso temos uma referência a esse arquivo no import.
Assim a nossa tela de login será definida no arquivo login_page.dart.
Para iniciar vamos incluir o código abaixo neste arquivo:
import
'package:flutter/material.dart'; class LoginPage extends StatelessWidget {
@override |
No código acima estamos usando o widget Scaffold e usando o argumento body para definir o método _body() onde vamos a seguir criar a tela de login.
Para criar a tela de login vamos usar um widget Form tendo como filho um widget ListView e neste widget usar um array de widgets para empilhar os widgets TextFormFields e RaisedButton.
Nota: Para saber mais sobre o widget Form, veja meu artigo : Criando formulários com validação
_body(BuildContext context) {
return Form(
child: ListView(
children: <Widget>[
textFormFieldLogin(),
textFormFieldSenha(),
containerButton(context)
],
)
);
}
|
Para organizar o código e torná-lo mais legível definimos 3 métodos como filhos do ListView onde vamos implementar as funcionalidades.
1- textFormFieldLogin - Vamos implementar a entrada do usuário para o Login
textFormFieldLogin() {
return TextFormField(
keyboardType: TextInputType.text,
style: TextStyle(color: Colors.black),
decoration: InputDecoration(
labelText: "Login",
labelStyle: TextStyle(fontSize:20.0, color: Colors.black),
hintText: "Informe o login"
)
);
}
|
Aqui usamos o widget TextFormField definindo o tipo de teclado e usando um InputDecoration para criar uma Label com um estilo e uma dica de texto.(hintText)
2- textFormFieldSenha - Vamos implementar a entrada do usuário para a Senha
textFormFieldSenha() {
return TextFormField(
obscureText: true,
keyboardType: TextInputType.text,
style: TextStyle(color: Colors.black),
decoration: InputDecoration(
labelText: "Senha",
labelStyle: TextStyle(fontSize:20.0, color: Colors.black),
hintText: "Informe a senha"
)
);
}
|
Repetimos aqui o código acima, a diferença é o uso do obscureText para ocultar a senha.
3- containerButton(context)
containerButton(BuildContext context) {
return Container(
height: 40.0,
margin: EdgeInsets.only(top: 10.0),
child: RaisedButton(
color: Colors.blue,
child: Text("Login",
style: TextStyle(color: Colors.white, fontSize: 20.0)),
onPressed: () { _onClickLogin(context); },
),
);
}
|
Aqui retornamos um Container cujo filho é um RaisedButton onde temos o callback onPressed definindo o método _onClickLogin(context).
Abaixo temos a implementação do método _onClickLogin():
_onClickLogin(BuildContext context) {
if(login.isEmpty || senha.isEmpty) {
showDialog(context: context,
builder: (context){
return AlertDialog(
title:Text("Erro"),
content: Text("Login e/ou Senha inválido(s)"),
actions : <Widget>[
FlatButton(
child: Text("OK"),
onPressed: () {
Navigator.pop(context);
}
)
]
);
},
);
}
}
|
![]() |
Nesta implementação estamos validando o login e a senha e exibindo uma mensagem ao usuário.
Usamos um AlertDialog e criamos uma Action contendo um FlatButton e um widget Text usando o callback onPressed() para poder fechar a caixa de diálogo de alerta que será exibida com a mensagem ao usuário.
Uma outra abordagem para fazer a validação é usar o recurso TextEditingController e a chave global do formulário - GlobalKey. Com isso além de poder fazer a validação poderemos obter e tratar as informações digitadas pelo usuário nos widgets TextFormField.
Para essa abordagem temos que alterar o código incluindo o código destacado nas linhas azuis:
import 'package:flutter/material.dart';
class LoginPage extends StatelessWidget {
final _tLogin = TextEditingController();
final _tSenha = TextEditingController();
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Fazer o Login"),
),
body: Padding(
padding: EdgeInsets.all(16.0),
child: _body(context),
),
);
}
String _validateLogin(String text){
if(text.isEmpty){
return "Informe o login";
}
return null;
}
String _validateSenha(String text){
if(text.isEmpty){
return "Informe a senha";
}
return null;
}
_body(BuildContext context) {
return Form(
key: _formKey,
child: ListView(
children: <Widget>[
textFormFieldLogin(),
textFormFieldSenha(),
containerButton(context)
],
)
);
}
TextFormField textFormFieldLogin() {
return TextFormField(
controller: _tLogin,
validator: _validateLogin,
keyboardType: TextInputType.text,
style: TextStyle(color: Colors.black),
decoration: InputDecoration(
labelText: "Login",
labelStyle: TextStyle(fontSize:20.0, color: Colors.black),
hintText: "Informe a senha"
)
);
}
TextFormField textFormFieldSenha() {
return TextFormField(
controller: _tSenha,
validator: _validateSenha,
obscureText: true,
keyboardType: TextInputType.text,
style: TextStyle(color: Colors.black),
decoration: InputDecoration(
labelText: "Senha",
labelStyle: TextStyle(fontSize:20.0, color: Colors.black),
hintText: "Informe a senha"
)
);
}
Container containerButton(BuildContext context) {
return Container(
height: 40.0,
margin: EdgeInsets.only(top: 10.0),
child: RaisedButton(
color: Colors.blue,
child: Text("Login",
style: TextStyle(color: Colors.white, fontSize: 20.0)),
onPressed: () { _onClickLogin(context); },
),
);
}
_onClickLogin(BuildContext context) {
final login = _tLogin.text;
final senha = _tSenha.text;
print("Login: $login , Senha: $senha " );
if(!_formKey.currentState.validate()) {
return;
}
if(login.isEmpty || senha.isEmpty) {
showDialog(context: context,
builder: (context){
return AlertDialog(
title:Text("Erro"),
content: Text("Login e/ou Senha inválido(s)"),
actions : <Widget>[
FlatButton(
child: Text("OK"),
onPressed: () {
Navigator.pop(context);
}
)
]
);
},
);
}
}
}
|
Vamos entender o código:
1- Criamos as variáveis _tedLogin e _tedSenha para gerenciar as informações entradas no TextFormField, e, criamos uma chave global - _formkey - para identificar o formulário:
final _tedLogin = TextEditingController();
final _tedSenha = TextEditingController();
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
2- Definimos dois métodos para validar login e senha:
... String _validaLogin(String text){ if(text.isEmpty){ return "Informe o login"; } return null; } String _validaSenha(String text){
if(text.isEmpty){
return "Informe a senha";
}
return null;
}
... |
3- Atribuimos a chave global ao Form:
... _body(BuildContext context) { return Form( key: _formKey, .... |
4- Atribuimos os valores aos argumentos controller e validator de cada TextFormField:
... TextFormField textFormFieldLogin() { return TextFormField( controller: _tLogin, validator: _validateLogin, ... |
... TextFormField textFormFieldSenha() { return TextFormField( controller: _tSenha, validator: _validateSenha, ... |
5- No método _onClickLogin() obtemos o login e senha informados e exibimos no console e validamos o formulário usando a chave global:
... _onClickLogin(BuildContext context) { final login = _tLogin.text; final senha = _tSenha.text; print("Login: $login , Senha: $senha " );
if(!_formKey.currentState.validate()) {
return;
}
.... |
Essa abordagem não exibe a caixa de diálogo de alerta pois já mostra ao usuário a mensagem para informar os valores quando isso não for feito.
Assim, na verdade não vamos precisar do código que faz a validação do login e senha conforme abaixo:
if(login.isEmpty || senha.isEmpty) { showDialog(context: context, builder: (context){ return AlertDialog( title:Text("Erro"), content: Text("Login e/ou Senha inválido(s)"), actions : <Widget>[ FlatButton( child: Text("OK"), onPressed: () { Navigator.pop(context); } ) ] ); }, ); } |
Temos assim a nossa tela de login criada e pronta para ser usada.
Na próxima parte do artigo vamos implementar a WEB API e fazer a autenticação do usuário.
Pegue o código
completo aqui:
main_login_page.dart
"Bom é louvar ao SENHOR, e cantar louvores ao teu
nome, ó Altíssimo;
Para de manhã anunciar a tua benignidade, e todas as noites a tua fidelidade;"
Salmos 92:1,2
Referências:
Super DVD Vídeo Aulas - Vídeo Aula sobre VB .NET, ASP .NET e C#
Super DVD C# - Recursos de aprendizagens e vídeo aulas para C#
Curso Fundamentos da Programação Orientada a Objetos com VB .NET
Flutter - Apresentando o widget MaterialApp - Macoratti
Flutter - Apresentando Flutter Studio - Macoratti
Flutter - Lista Básica - Macoratti
Flutter - Apresentando Widgets - Macoratti
Flutter - Obtendo dados da Web - Macoratti