Programação para Dispositivos Móveis
Flutter
Aula 06
Prof. Dr. Rodrigo Plotze
Roteiro
▪ Material Design
▪ Scaffold
▪ Text
▪ Column e Row
▪ Stateful Widgets
2
MATERIAL DESIGN
3
Material Design
▪ Linguagem de design desenvolvida pela Google
em 2014.
▪ Referência para o design de
UI para aplicativos.
https://material.io/design/
4
Material Design
▪ Material App
− Um widget que agrupa vários widgets normalmente
necessários para aplicativos com material design.
− Um widget MaterialApp é definido apenas uma vez no
aplicativo.
− Propriedades
• title: título do aplicativo.
• theme: tema empregado no App, que permite a
configuração de diversos atributos.
• home: primeira tela a ser mostrado no App.
5
Material Design
MaterialApp(
theme: ThemeData(
primaryColor: Colors.blue,
accentColor: Colors.green,
textTheme: TextTheme(body1:
TextStyle(
color: Colors.purple)
),
),
6
SCAFFOLD
7
Scaffold
▪ Principal estrutura de layout do Material Design.
▪ Propriedades
− appBar
− body
− drawer
− floatingActionButton
− bottomNavigationBar
− persistentFooterButtons
8
Material Design
import 'package:flutter/material.dart';
class ScaffoldWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Scaffold Widget"),
centerTitle: true,
),
body: Container(color: Colors.blue[100]),
drawer: Container(color: Colors.red, ),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {print("Botão pressionado!");} ,
),
bottomNavigationBar: BottomAppBar(
child: Container(
child: Text("Barra status"),
height: 30.0,
alignment: Alignment.centerLeft,
),
color: Colors.blue[600],
),
persistentFooterButtons: <Widget>[
IconButton(icon: Icon(Icons.access_time),
onPressed: () {print("Alarme");}), ],
);
}
} 9
Material Design
import 'package:flutter/material.dart';
class ScaffoldWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Scaffold Widget"),
centerTitle: true,
),
body: Container(color: Colors.blue[100]),
drawer: Container(color: Colors.red, ),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {print("Botão pressionado!");} ,
),
bottomNavigationBar: BottomAppBar(
child: Container(
child: Text("Barra status"),
height: 30.0,
alignment: Alignment.centerLeft,
),
color: Colors.blue[600],
),
persistentFooterButtons: <Widget>[
IconButton(icon: Icon(Icons.access_time),
onPressed: () {print("Alarme");}), ],
);
}
} 10
Material Design
import 'package:flutter/material.dart';
class ScaffoldWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Scaffold Widget"),
centerTitle: true,
),
body: Container(color: Colors.blue[100]),
drawer: Container(color: Colors.red, ),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {print("Botão pressionado!");} ,
),
bottomNavigationBar: BottomAppBar(
child: Container(
child: Text("Barra status"),
height: 30.0,
alignment: Alignment.centerLeft,
),
color: Colors.blue[600],
),
persistentFooterButtons: <Widget>[
IconButton(icon: Icon(Icons.access_time),
onPressed: () {print("Alarme");}), ],
);
}
} 11
Material Design
import 'package:flutter/material.dart';
class ScaffoldWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Scaffold Widget"),
centerTitle: true,
),
body: Container(color: Colors.blue[100]),
drawer: Container(color: Colors.red, ),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {print("Botão pressionado!");} ,
),
bottomNavigationBar: BottomAppBar(
child: Container(
child: Text("Barra status"),
height: 30.0,
alignment: Alignment.centerLeft,
),
color: Colors.blue[600],
),
persistentFooterButtons: <Widget>[
IconButton(icon: Icon(Icons.access_time),
onPressed: () {print("Alarme");}), ],
);
}
} 12
Material Design
import 'package:flutter/material.dart';
class ScaffoldWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Scaffold Widget"),
centerTitle: true,
),
body: Container(color: Colors.blue[100]),
drawer: Container(color: Colors.red, ),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {print("Botão pressionado!");} ,
),
bottomNavigationBar: BottomAppBar(
child: Container(
child: Text("Barra status"),
height: 30.0,
alignment: Alignment.centerLeft,
),
color: Colors.blue[600],
),
persistentFooterButtons: <Widget>[
IconButton(icon: Icon(Icons.access_time),
onPressed: () {print("Alarme");}), ],
);
}
} 13
Material Design
import 'package:flutter/material.dart';
class ScaffoldWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Scaffold Widget"),
centerTitle: true,
),
body: Container(color: Colors.blue[100]),
drawer: Container(color: Colors.red, ),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {print("Botão pressionado!");} ,
),
bottomNavigationBar: BottomAppBar(
child: Container(
child: Text("Barra status"),
height: 30.0,
alignment: Alignment.centerLeft,
),
color: Colors.blue[600],
),
persistentFooterButtons: <Widget>[
IconButton(icon: Icon(Icons.access_time),
onPressed: () {print("Alarme");}), ],
);
}
} 14
TEXT
15
Text
▪ Widget Text exibe
uma sequência de
texto com estilo Text.rich(
TextSpan(
único. text: 'Hello', // default text style
children: <TextSpan>[
▪ A cadeia de TextSpan(text: ' beautiful ', style: Tex
tStyle(fontStyle: FontStyle.italic)),
TextSpan(text: 'world', style: TextStyle
caracteres pode (fontWeight: FontWeight.bold)),
],
quebrar várias linhas )
),
ou pode ser exibida O construtor Text.rich pode exibir
na mesma linha, um parágrafo com TextSpans com
dependendo das estilos diferentes.
restrições de layout.
16
Text
Text("Programando com Flutter!",
style: TextStyle(
color: Colors.red,
fontSize: 35.0,
fontStyle: FontStyle.italic,
fontWeight: FontWeight.bold,
decoration: TextDecoration.underline,
decorationColor: Colors.blue,
decorationStyle: TextDecorationStyle.dashed,
),
),
17
COLUMN E ROW
18
Column e Row
▪ Column
− Widget utilizado para Widget 1
exibir widgets filhos
em um arranjo Widget 2
vertical.
Widget 3
19
Column e Row
▪ Row
− Widget utilizado para Widget 1 Widget 2 Widget 3
exibir widgets filhos
em um arranjo
vertical.
20
Column e Row
Column(
children: <Widget>[
Icon(
Icons.sentiment_very_satisfied,
size: 80.0,
color: Colors.orange
),
Icon(
Icons.sentiment_satisfied,
size: 80.0,
color: Colors.orange
),
Icon(
Icons.sentiment_neutral,
size: 80.0,
color: Colors.orange
),
],)
21
Column e Row
Column(
children: <Widget>[
Icon(
Icons.sentiment_very_satisfied,
size: 80.0,
color: Colors.orange
),
Icon(
Icons.sentiment_satisfied,
size: 80.0,
color: Colors.orange
),
Icon(
Icons.sentiment_neutral,
size: 80.0,
color: Colors.orange
),
],)
22
Column e Row
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(
Icons.sentiment_very_satisfied,
size: 80.0,
color: Colors.orange
),
Icon(
Icons.sentiment_satisfied,
size: 80.0,
color: Colors.orange
),
Icon(
Icons.sentiment_neutral,
size: 80.0,
color: Colors.orange
),
],)
23
Column e Row
Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Icon(
Icons.sentiment_very_satisfied,
size: 80.0,
color: Colors.orange
),
Icon(
Icons.sentiment_satisfied,
size: 80.0,
color: Colors.orange
),
Icon(
Icons.sentiment_neutral,
size: 80.0,
color: Colors.orange
),
],)
24
Column e Row
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Icon(
Icons.sentiment_very_satisfied,
size: 80.0,
color: Colors.orange
),
Icon(
Icons.sentiment_satisfied,
size: 80.0,
color: Colors.orange
),
Icon(
Icons.sentiment_neutral,
size: 80.0,
color: Colors.orange
),
],)
25
Alinhamento do Column
26
Alinhamento Row
27
STATEFUL
28
O que são Stateful Widgets?
▪ São widgets que tem seu estado alterado.
▪ Utilizados sempre que é necessário realizar
alterações nos widgets da UI.
▪ Um Stateful Widget é composto por:
– uma classe StatefulWidget
– uma classe State
29
O que são Stateful Widgets?
▪ São widgets que tem seu estado alterado.
▪ Utilizados sempre que é necessário realizar
alterações nos widgets da UI.
▪ Um Stateful Widget é composto por:
– uma classe StatefulWidget
– uma classe State
Responsável pela inicialização
da classe State.
30
O que são Stateful Widgets?
▪ São widgets que tem seu estado alterado.
▪ Utilizados sempre que é necessário realizar
alterações nos widgets da UI.
▪ Um Stateful Widget é composto por:
– uma classe StatefulWidget
– uma classe State
A classe State contém as
variáveis e informa a classe
StatefulWidget quando e como
se construir.
31
O que são Stateful Widgets?
▪ São widgets que tem seu estado alterado.
▪ Utilizados sempre que é necessário realizar
alterações nos widgets da UI.
▪ Um Stateful Widget é composto por:
– uma classe StatefulWidget
– uma classe State
O método setState é usado
para notificar que o estado
interno de um objeto foi
alterado.
32
Stateful
class Exemplo extends StatefulWidget {
@override
_ExemploState createState() => _ExemploState();
}
class _ExemploState extends State<Exemplo> {
@override
Widget build(BuildContext context) {
return Container(
);
}
}
33
APP
CALCULADORA IMC
34
App Calculadora IMC
▪ Objetivo
− Desenvolver um App para
calcular o Índice de Massa
Corporal (IMC)
35
App Calculadora IMC
Principais widgets:
▪ Scaffold
▪ IconButton
▪ Form
▪ Icon
▪ TextFormField
▪ RaisedButton
36
App Calculadora IMC
Principais widgets:
▪ Scaffold
▪ IconButton
▪ Form
▪ Icon
▪ TextFormField
▪ RaisedButton
37
App Calculadora IMC
Principais widgets:
▪ Scaffold
▪ IconButton
▪ Form
▪ Icon
▪ TextFormField
▪ RaisedButton
38
App Calculadora IMC
Principais widgets:
▪ Scaffold
▪ IconButton
▪ Form
▪ Icon
▪ TextFormField
▪ RaisedButton
39
App Calculadora IMC
Principais widgets:
▪ Scaffold
▪ IconButton
▪ Form
▪ Icon
▪ TextFormField
▪ RaisedButton
40
App Calculadora IMC
import 'package:flutter/material.dart';
import 'package:app_imc/widget_imc.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: "Calculadora IMC",
home: ImcWidget(),
);
}
}
41
App Calculadora IMC
import 'package:flutter/material.dart';
class ImcWidget extends StatefulWidget {
@override
_ImcWidgetState createState() => _ImcWidgetState();
}
class _ImcWidgetState extends State<ImcWidget> {
GlobalKey<FormState> _formkey = GlobalKey<FormState>();
TextEditingController txtPeso = TextEditingController();
TextEditingController txtAltura = TextEditingController();
String _resultado = "";
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Calculadora de IMC"),
backgroundColor: Colors.green,
actions: <Widget>[
IconButton(
icon: Icon(Icons.refresh),
onPressed: () { /*_reset();*/ })
],),
body: null,
backgroundColor: Colors.white);
}
} 42
App Calculadora IMC
import 'package:flutter/material.dart';
class ImcWidget extends StatefulWidget {
@override
_ImcWidgetState createState() => _ImcWidgetState();
}
class _ImcWidgetState extends State<ImcWidget> {
GlobalKey<FormState> _formkey = GlobalKey<FormState>();
TextEditingController txtPeso = TextEditingController();
TextEditingController txtAltura = TextEditingController(); GlobalKeys
String _resultado = "";
▪ Identificam exclusivamente os
@override elementos.
Widget build(BuildContext context) { ▪ Fornecem acesso a outros
return Scaffold(
objetos associados a esses
appBar: AppBar(
title: Text("Calculadora de IMC"), elementos, como BuildContext.
backgroundColor: Colors.green, ▪ Para StatefulWidgets, as chaves
actions: <Widget>[ globais também fornecem
IconButton( acesso ao State.
icon: Icon(Icons.refresh),
onPressed: () {/*_reset();*/ })
],),
body: null,
backgroundColor: Colors.white);
}
} 43
App Calculadora IMC
import 'package:flutter/material.dart';
class ImcWidget extends StatefulWidget {
@override
_ImcWidgetState createState() => _ImcWidgetState();
}
class _ImcWidgetState extends State<ImcWidget> {
GlobalKey<FormState> _formkey = GlobalKey<FormState>();
TextEditingController txtPeso = TextEditingController();
TextEditingController txtAltura = TextEditingController();
String _resultado = "";
@override TextEditingController
Widget build(BuildContext context) {
return Scaffold( ▪ Um controlador para um campo de
appBar: AppBar( texto editável.
title: Text("Calculadora de IMC"),
backgroundColor: Colors.green,
▪ Sempre que o usuário modifica um
actions: <Widget>[ campo de texto com um
IconButton( TextEditingController associado, o
icon: Icon(Icons.refresh), campo de texto atualiza o valor e o
onPressed: () {/*_reset();*/ }) controlador notifica seus ouvintes.
],), ▪ Os ouvintes podem ler as
body: null, propriedades de texto e seleção para
backgroundColor: Colors.white);
}
saber o que o usuário digitou ou
} como a seleção foi atualizada.
44
App Calculadora IMC
import 'package:flutter/material.dart';
class ImcWidget extends StatefulWidget {
@override
_ImcWidgetState createState() => _ImcWidgetState();
}
class _ImcWidgetState extends State<ImcWidget> {
GlobalKey<FormState> _formkey = GlobalKey<FormState>();
TextEditingController txtPeso = TextEditingController();
TextEditingController txtAltura = TextEditingController();
String _resultado = "";
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Calculadora de IMC"),
backgroundColor: Colors.green,
actions: <Widget>[
IconButton(
icon: Icon(Icons.refresh),
onPressed: () {/*_reset();*/ })
],),
body: null,
backgroundColor: Colors.white);
}
} 45
App Calculadora IMC
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Calculadora de IMC"),
backgroundColor: Colors.green,
actions: <Widget>[
IconButton(icon: Icon(Icons.refresh), onPressed: () {/*_reset();*/ })
],
),
body: SingleChildScrollView(
padding: const EdgeInsets.all(20.0),
child: Form(
key: _formkey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Icon(Icons.people, size: 80, color: Colors.green[900]),
//campos do formulário
]),
),
),
backgroundColor: Colors.white); 46
}
App Calculadora IMC
campoTexto(rotulo, controle) {
return Container(
padding: const EdgeInsets.symmetric(vertical: 5),
child: TextFormField(
keyboardType: TextInputType.number,
style: TextStyle(color: Colors.green[900], fontSize: 20),
decoration: InputDecoration(
labelText: rotulo,
labelStyle: TextStyle(
color: Colors.green[500],
fontSize: 12,
),
),
controller: controle,
validator: (value) {
return (value.isEmpty) ? "Informe o valor" : null;
},
),
);
}
Chamar método no body do Scaffold (abaixo do Icon).
campoTexto("Peso", txtPeso),
campoTexto("Altura", txtAltura), 47
App Calculadora IMC
botaoCalcular(BuildContext context) {
return Container(
padding: const EdgeInsets.only(top: 20),
child: RaisedButton(
child: Text(
"calcular",
style: TextStyle(
color: Colors.white,
fontSize: 18,
),
),
color: Colors.grey[500],
onPressed: () {
if (_formkey.currentState.validate()) {
//_calcular();
}
},
));
}
Chamar método no body do Scaffold
botaoCalcular(context), 48
App Calculadora IMC
void _reset() {
setState(() {
txtPeso.text = ""; setState
txtAltura.text = "";
_resultado = ""; ▪ Notifique o framework que o estado
}); interno deste objeto foi alterado.
}
void _calcular() {
setState(() {
double peso = double.parse(txtPeso.text);
double altura = double.parse(txtAltura.text);
double imc = peso / pow(altura, 2);
_resultado = "Resultado\nIMC = ${imc.toStringAsPrecision(2)}";
});
} import 'dart:math';
exibirResultado() {
return Container(
padding: EdgeInsets.only(top: 20),
child: Text(_resultado,
style: TextStyle(color: Colors.green[900], fontSize: 20)),
);
}
49
App Calculadora IMC
Adicionar a chamada do método exibirResultado
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Icon(Icons.people, size: 80, color: Colors.green[900]),
campoTexto("Peso", txtPeso),
campoTexto("Altura", txtAltura),
botaoCalcular(context),
exibirResultado(),
]),
Remover o comentário da chamada _reset()
Remover o comentário da chamada _calcular() e adicionar a linha abaixo para não ocorrer
problemas em relação ao foco.
FocusScope.of(context).requestFocus(new FocusNode());
50
App Calculadora IMC
51
App Calculadora IMC
Para exibir o resultado na forma de uma caixa de diálogo
exibirResultadoDialog(BuildContext context) {
return showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text("Calculadora IMC"),
content: Text(_resultado),
actions: <Widget>[
FlatButton(
child: Text("ok"),
onPressed: () {
Navigator.pop(context);
},
)
],
);
}, onPressed: () {
); if (_formkey.currentState.validate()) {
_calcular();
} FocusScope.of(context).requestFocus(new FocusNode());
exibirResultadoDialog(context);
}
}, 52
ATIVIDADE PRÁTICA
53
Atividade Prática
1. Construir um App a partir do seguinte protótipo:
54
Atividade Prática
2. Construir um App a partir do seguinte protótipo:
55
Atividade Prática
3. Construir um App a partir do seguinte protótipo:
56
FIM
57