Flutter - Apresentando Layouts - V
Hoje veremos o conceito de Layouts no Flutter. (baseado na documentação oficial) |
|
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
Continuando a quarta parte do artigo vamos tratar a interação com o usuário.
Interagindo com o usuário
Até o momento
vimos que os widgets são modelos ou templates para tudo o que você pode ver (e
muitas coisas que você não consegue ver) na interface do usuário. Vimos também
que widgets simples podem ser combinados para criar layouts complexos. A maioria
desses layouts pode ser construída dividindo seu design em linhas (widget
Row), colunas (widget Colunm)
e camadas (widget Stack).
Tudo bem, mas até o momento todos esses layouts usados eram estáticos. Eles não
interagem com ninguém e não reagem a nenhuma ação, ou seja não fazem nada.
Neste artigo vamos explorar como realmente fazer algo quando o usuário interage
com os widgets que adicionamos ao nosso layout. A ênfase será em exemplos
simples e fáceis de reproduzir. Eu recomendo que você trabalhe enquanto passamos
por cada um deles. Faça pequenas alterações no código e veja como isso afeta o
comportamento. Isso aumentará muito o seu aprendizado geral.
Widgets e o estado(State)
Os
Widgets são imutáveis. Ou seja, eles não podem ser
alterados. Quaisquer propriedades que eles contenham são finais e só podem ser definidas quando o widget for
inicializado. Isso os mantém leves, de modo que é barato recriá-los quando a
árvore de widgets for alterada.
Assim, existem dois tipos de widgets:
Em nosso exemplos estamos usando widgets sem estado ou StatelessWidget.
Os
StatelessWidgets não possuem nenhum estado. Ou
seja, eles não têm variáveis mutáveis. Então, se temos uma variável que
queremos mudar, então precisamos usar um StatefulWidget
ou um widget com estado.
Os StatefulWidgets funcionam assim:
- Existe uma classe StatefulWidget e uma classe
State.
- A classe StatefulWidget inicializa a classe
State.
- A classe State contém as variáveis e informa a classe
StatefulWidget quando
e como se construir.
Dessa forma sempre que precisarmos de um StatefulWidget, temos que criar duas classes:
Aqui está a configuração básica da estrutura de um StatefulWidget :
// a classe do widget class
class MeuWidget extends StatefulWidget {
@override
_MeuWidgetState createState() => _MeuWidgetState();
}
// a classe de estado ou state
class _MeuWidgetState extends State<MeuWidget> {
@override
Widget build(BuildContext context) {
return ...; // widget layout
}
}
|
Note que :
Agora que já sabemos como os Widgets se comportam vamos usar widgets que respondem a ação do usuário.
Vamos criar um projeto no VS Code chamado flutter_entrada_usuario e definir o código abaixo no arquivo main.dart :
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter',
home: Scaffold(
appBar: AppBar(
title: Text('Flutter'),
),
body: MeuWidget(),
),
);
}
}
|
Neste código definindo o método main() e criando um widget sem estado StatelessWidget chamado MyApp que usa o MaterialApp, o Scaffold e define um AppBar com texto.
Na propriedade body definimos o widget MeuWidget que iremos criar a seguir. Esse widget possui estado e deve estender de StatefulWidget.
Usando widgets responsivos
1- Button
Os Buttons são muito usados e o Flutter tem vários tipos de widgets Buttons como :
Vamos agora definir o widget MeuWidget como um widget com estado que deve herdar de StatefulWidget.
Como estamos usando o VS Code podemos usar atalhos para gerar trechos de código padronizados.
A extensão
Flutter inclui os seguintes atalhos:
- Prefixo stless: Crie uma nova subclasse de
StatelessWidget.
- Prefixo stful: crie uma nova subclasse de
StatefulWidget e sua subclasse de estado associada.
- Prefixo stanim: crie uma nova subclasse de
StatefulWidget e sua subclasse de estado associada, incluindo um campo
inicializado com um AnimationController.
Então para criar um StatefulWidget digitamos stful e veremos as opções disponíveis:
Selecionando : Flutter stateful widget veremos o bloco de código gerado abaixo. Basta então completa digitando o nome da classe: MeuWidget.
Vamos então completar o código definindo no widget MeuWidget usando um Column com dois filhos: Text e RaisedButton, onde no Button definimos o método onPressed() fazendo uma chamada para o método _fazerAlgo():
class MeuWidget extends StatefulWidget {
@override
_MeuWidgetState createState() => _MeuWidgetState();
}
String _textoString = "Macoratti .net - Flutter";
class _MeuWidgetState extends State<MeuWidget>
{
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Text(_textoString, style: TextStyle(fontSize: 30),
),
RaisedButton(
child: Text('Meu Botão'), onPressed: () {
_fazerAlgo();
}
),
],
);
}
void _fazerAlgo() { // Usando a chamada State.setState() estado atualizando // o valor do state da variável _textoString. setState(() { _textoString = 'Olá Flutter'; }); } } |
Executando o código e pressionando no botão agora veremos que o valor do texto vai ser alterado de 'Macoratti .net - Flutter' para 'Olá Flutter'.
Aqui destacamos o seguinte:
2- TextFields
O widget
textfield permite que o usuário insira texto, seja
com o teclado do hardware ou com um teclado na tela.
Este widget chama o callback onChanged sempre que o
usuário altera o texto no campo. Se o usuário indicar que está pronto para
digitar no campo (por exemplo, pressionando um botão no teclado virtual),
o campo de texto chama o callback onSubmitted.
Neste exemplo vamos criar um layout contendo um widget Text e um widget TextField onde sempre que o TextField mudar o valor de Text será atualizado.
Substitua o código da classe _MeuWidgetState pelo código a seguir:
class MeuWidget extends StatefulWidget {
@override
_MeuWidgetState createState() => _MeuWidgetState();
}
String _textoString = "Macoratti .net - Flutter";
class _MeuWidgetState extends State<MeuWidget> {
@override
Widget build(BuildContext context) {
return Column(
children: [
Text(_textoString,
style: TextStyle(fontSize: 20),
),
TextField(
onChanged: (texto) {
_fazerAlgo(texto);
},
)
],
);
}
void _fazerAlgo(String texto) {
// Usando a chamada State.setState() estado atualizando
// o valor do state da variável _textoString.
setState(() {
_textoString = texto;
});
}
}
|
Observe que o
widget
TextField tem
um parâmetro onChanged para um método de retorno de
chamada. Este método fornece a string atual após uma alteração ter sido feita.
Se você deseja obter o valor do texto sem ouvir onChanged,
é possível definir o parâmetro Controller do
TextField.
2- Checkboxes
A caixa de
seleção não mantém nenhum estado. Em vez disso, quando o estado da caixa de
seleção é alterado, o widget chama o callback onChanged.
A maioria dos widgets que usam uma caixa de seleção escutará o callback
onChanged e reconstruirá a caixa de seleção com um
novo valor para atualizar a aparência visual da caixa de seleção.
A caixa de seleção pode exibir, opcionalmente, três valores -
true, false e null - se a propriedade
tristate for true.
Quando o valor é null, um traço é exibido. Por
padrão, tristate é false
e o valor da caixa de seleção deve ser true ou false.
Para o exemplo deste artigo vamos usar um CheckboxListTile que combina uma caixa de seleção com uma label.
Substitua o código da classe _MeuWidgetState pelo código a seguir:
class MeuWidget extends StatefulWidget {
@override
_MeuWidgetState createState() => _MeuWidgetState();
}
bool _checkedValue = false;
class _MeuWidgetState extends State<MeuWidget> {
@override
Widget build(BuildContext context) {
return CheckboxListTile(
title: Text('Este é um título'),
value: _checkedValue,
onChanged: (novoValor) {
_fazerAlgo(novoValor);
},
// definindo o controlAffinity para leading faz
// com que a caixa de seleção seja exibida antes
//do título em vez de depois
controlAffinity: ListTileControlAffinity.leading,
);
}
void _fazerAlgo(bool isChecked) {
// Usando a chamada State.setState() estado atualizando
// o valor do state da variável _textoString.
setState(() {
_checkedValue = isChecked;
});
}
} |
Se você quiser
criar uma caixa de seleção personalizada, poderá usar o widget
Checkbox que não tem um título incluído.
Tente comentar a linha controlAffinity para ver
como isso afeta o layout.
3- Dialogs
Existem alguns tipos de diálogos no Flutter, mas vamos ver um comum: o AlertDialog que não é difícil de configurar e que contém uma mensagem e alguns botões.
Nota: O widget Dialog não tem opinião sobre o conteúdo do diálogo. Em vez de usar esse widget diretamente, considere o uso de AlertDialog ou SimpleDialog, que implementam tipos específicos de diálogos de material design.
Substitua o código da classe _MeuWidgetState pelo código a seguir:
class MeuWidget extends StatefulWidget {
@override
_MeuWidgetState createState() => _MeuWidgetState();
}
class _MeuWidgetState extends State<MeuWidget> {
@override
Widget build(BuildContext context) {
return RaisedButton(
child: Text('Clique Aqui para ver o Dialog'),
onPressed: () {
_showAlertDialog();
},
);
}
void _showAlertDialog() {
// configura o button
Widget okButton = FlatButton(
child: Text("OK"),
onPressed: () {
// Navigator fecha a caixa de diálogo.
//`context` significa o BuildContext,
// que esta disponível por padrão dentro de
// um objeto State. Se você está trabalhando
// com um AlertDialog em um StatelessWidget,
// então você precisaria passar uma referência
// ao BuildContext.
Navigator.pop(context);
},
);
// configura um AlertDialog
AlertDialog alert = AlertDialog(
title: Text("Titulo do Dialog"),
content: Text("Este é um AlertDialog."),
actions: [
okButton,
],
);
// exibe o dialog
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
}
}
|
Um AlertDialog precisa do BuildContext. Isso é passado para o método build() e também é uma propriedade do objeto State.
O widget
Navigator é usado para fechar o diálogo e gerencia
um conjunto de widgets filhos com uma disciplina de pilha.
Na próxima
parte do artigo iremos tratar dos detectores de gestos.
"Arrependei-vos, pois, e convertei-vos, para que sejam apagados os vossos
pecados, e venham assim os tempos do refrigério pela presença do Senhor,
E envie ele a Jesus Cristo, que já dantes vos foi pregado."
Atos 3:19-20
Veja os
Destaques e novidades do SUPER DVD Visual Basic
(sempre atualizado) : clique e confira !
Quer migrar para o VB .NET ?
Quer aprender C# ??
Quer aprender os conceitos da Programação Orientada a objetos ? Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ? |
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
https://docs.flutter.io/flutter/widgets/Navigator-class.html