Escolar Documentos
Profissional Documentos
Cultura Documentos
eu
Machine Translated by Google
Sobre o Tutorial
Flutter é uma estrutura de código aberto para criar aplicativos móveis de alta qualidade e alto desempenho
em sistemas operacionais móveis - Android e iOS. Ele fornece um SDK simples, poderoso, eficiente e fácil
de entender para escrever aplicativos móveis na própria linguagem do Google, Dart.
Este tutorial aborda os fundamentos do framework Flutter, instalação do Flutter SDK, configuração do
Android Studio para desenvolver aplicativos baseados em Flutter, arquitetura do Flutter
framework e desenvolvimento de todos os tipos de aplicativos móveis usando o framework Flutter.
Público
Este tutorial foi preparado para profissionais que desejam fazer carreira na área de aplicativos móveis. Este tutorial tem como
objetivo deixá-lo confortável para começar a usar o framework Flutter e suas diversas funcionalidades.
Pré-requisitos
Este tutorial foi escrito assumindo que os leitores já estão cientes do que é um Framework e que os leitores
têm um conhecimento sólido em Programação Orientada a Objetos e conhecimentos básicos em
framework Android e programação Dart.
Se você é iniciante em algum desses conceitos, sugerimos que você leia primeiro os tutoriais relacionados
a eles, antes de começar a usar o Flutter.
Todo o conteúdo e gráficos publicados neste e-book são propriedade da Tutorials Point (I)
Unip. Ltd. O usuário deste e-book está proibido de reutilizar, reter, copiar, distribuir ou republicar qualquer
conteúdo ou parte do conteúdo deste e-book de qualquer maneira sem o consentimento por escrito do
editor.
Nós nos esforçamos para atualizar o conteúdo do nosso site e tutoriais da forma mais oportuna e precisa
possível; no entanto, o conteúdo pode conter imprecisões ou erros. Ponto de tutoriais (I) Unip.
Ltd. não oferece nenhuma garantia quanto à precisão, atualidade ou integridade de nosso site ou de
seu conteúdo, incluindo este tutorial. Se você descobrir algum erro em nosso site ou neste tutorial,
avise-nos em contact@tutorialspoint.com
eu
Machine Translated by Google
Vibração
Índice
eu
Machine Translated by Google
Vibração
iii
Machine Translated by Google
Vibração
4
Machine Translated by Google
1. Vibração – Introdução
Em geral, desenvolver uma aplicação móvel é uma tarefa complexa e desafiadora. Existem muitos
frameworks disponíveis para desenvolver um aplicativo móvel. O Android fornece uma estrutura nativa
baseada na linguagem Java e o iOS fornece uma estrutura nativa baseada na linguagem Objective-C/Shift.
No entanto, para desenvolver uma aplicação que suporte ambos os sistemas operacionais, precisamos
codificar em duas linguagens diferentes usando dois frameworks diferentes. Para ajudar a superar essa
complexidade, existem estruturas móveis que suportam ambos os sistemas operacionais. Essas estruturas
variam desde estruturas simples de aplicativos móveis híbridos baseados em HTML (que usam HTML para
interface de usuário e JavaScript para lógica de aplicativo) até estruturas complexas específicas de
linguagem (que fazem o trabalho pesado de conversão de código em código nativo). Independentemente
da sua simplicidade ou complexidade, estas estruturas têm sempre muitas desvantagens, sendo uma das
principais desvantagens o seu desempenho lento.
Nesse cenário, o Flutter – um framework simples e de alto desempenho baseado na linguagem Dart,
oferece alto desempenho ao renderizar a UI diretamente na tela do sistema operacional ao invés de através
do framework nativo.
Flutter também oferece muitos widgets (UI) prontos para usar para criar um aplicativo moderno. Esses
os widgets são otimizados para o ambiente móvel e projetar o aplicativo usando widgets é tão simples
quanto projetar HTML.
Para ser mais específico, o próprio aplicativo Flutter é um widget. Os widgets Flutter também suportam
animações e gestos. A lógica da aplicação é baseada na programação reativa. O widget pode opcionalmente
ter um estado. Ao alterar o estado do widget, o Flutter irá automaticamente (programação reativa) comparar
o estado do widget (antigo e novo) e renderizar o widget apenas com as alterações necessárias, em vez
de renderizar novamente o widget inteiro.
Recursos do Flutter
A estrutura Flutter oferece os seguintes recursos aos desenvolvedores:
1
Machine Translated by Google
Vibração
Vantagens do Flutter
Flutter vem com widgets bonitos e personalizáveis para alto desempenho e excelente aplicativo móvel. Ele
atende a todas as necessidades e requisitos personalizados. Além dessas, o Flutter oferece muitas outras
vantagens conforme mencionado abaixo:
• O Dart possui um grande repositório de pacotes de software que permite ampliar os recursos do seu
aplicativo.
• Os desenvolvedores precisam escrever apenas uma única base de código para ambos os aplicativos
(plataformas Android e iOS). O Flutter também pode ser estendido para outras plataformas no futuro.
• Flutter precisa de menos testes. Devido à sua base de código única, é suficiente escrever testes
automatizados uma vez para ambas as plataformas.
• A simplicidade do Flutter o torna um bom candidato para desenvolvimento rápido. Sua capacidade de
personalização e extensibilidade o tornam ainda mais poderoso.
• Com o Flutter, os desenvolvedores têm controle total sobre os widgets e seu layout.
• Flutter oferece ótimas ferramentas para desenvolvedores, com incrível recarga a quente.
Desvantagens do Flutter
Apesar de suas muitas vantagens, o flutter tem as seguintes desvantagens:
• Como é codificado na linguagem Dart, um desenvolvedor precisa aprender uma nova linguagem (embora
seja fácil de aprender).
• A estrutura moderna tenta separar a lógica e a UI tanto quanto possível, mas, no Flutter, a interface do
usuário e a lógica são misturadas. Podemos superar isso usando codificação inteligente e módulo de
alto nível para separar a interface do usuário e a lógica.
• Flutter é mais uma estrutura para criar aplicativos móveis. Os desenvolvedores estão tendo dificuldade
em escolher as ferramentas de desenvolvimento certas em um segmento extremamente populoso.
2
Machine Translated by Google
Este capítulo irá guiá-lo detalhadamente pela instalação do Flutter em seu computador local.
Instalaçãono Windows
Nesta seção, vamos ver como instalar o Flutter SDK e seus requisitos em um sistema Windows.
Passo 1: Vá para URL, https://flutter.dev/docs/get-started/install/windows e baixe o Flutter SDK mais recente. Em abril de
2019, a versão é 1.2.1 e o arquivo é flutter_windows_v1.2.1-stable.zip.
Etapa 4: Flutter fornece uma ferramenta, flutter doctor, para verificar se todos os requisitos de desenvolvimento de flutter
foram atendidos.
médico agitado
Etapa 5: A execução do comando acima analisará o sistema e mostrará seu relatório conforme mostrado abaixo:
Resumo do médico (para ver todos os detalhes, execute flutter doctor -v):
[ÿ] Flutter (canal estável, v1.2.1, no Microsoft Windows [versão 10.0.17134.706], localidade en-US)
[ÿ] Conjunto de ferramentas Android - desenvolvimento para dispositivos Android (Android SDK versão 28.0.3)
O relatório diz que todas as ferramentas de desenvolvimento estão disponíveis, mas o dispositivo não está conectado.
Podemos corrigir isso conectando um dispositivo Android via USB ou iniciando um emulador de Android.
Etapa 6: instale o Android SDK mais recente, se relatado pelo flutter doctor
Etapa 7: instale o Android Studio mais recente, se relatado pelo flutter doctor
Etapa 9: Instale o plugin Flutter e Dart para Android Studio. Ele fornece um modelo de inicialização para criar um novo
aplicativo Flutter, uma opção para executar e depurar o aplicativo Flutter no próprio Android Studio, etc.,
3
Machine Translated by Google
Vibração
Instalação em MacOS
Para instalar o Flutter no MacOS, você terá que seguir os seguintes passos:
Etapa 1: vá para o URL, https://flutter.dev/docs/get-started/install/macos e baixe o Flutter SDK mais recente. Em abril de
2019, a versão é 1.2.1 e o arquivo é flutter_macos_v1.2.1-
estável.zip.
Etapa 3: atualize o caminho do sistema para incluir o diretório flutter bin (no arquivo ~/.bashrc).
Passo 4: Habilite o caminho atualizado na sessão atual usando o comando abaixo e verifique-o também.
fonte ~/.bashrc
fonte $HOME/.bash_profile echo
$PATH
Flutter fornece uma ferramenta, flutter doctor, para verificar se todos os requisitos de desenvolvimento de flutter foram
atendidos. É semelhante ao equivalente do Windows.
Etapa 6: instale o Android SDK mais recente, se relatado pelo flutter doctor
Etapa 7: instale o Android Studio mais recente, se relatado pelo flutter doctor
Etapa 8: inicie um emulador de Android ou conecte um dispositivo Android real ao sistema para desenvolver um
aplicativo Android.
Passo 9: Abra o simulador iOS ou conecte um dispositivo iPhone real ao sistema para desenvolver o aplicativo iOS.
Etapa 10: Instale o plugin Flutter e Dart para Android Studio. Ele fornece o modelo de inicialização para criar um novo
aplicativo Flutter, opção para executar e depurar o aplicativo Flutter no próprio Android Studio, etc.,
4
Machine Translated by Google
Vibração
3. Flutter – Criando Aplicativo Simples no
Android Studio
Neste capítulo, vamos criar um aplicativo Flutter simples para entender os fundamentos da criação de um aplicativo Flutter
no Android Studio.
Etapa 2: Criar projeto Flutter. Para isso, clique em Arquivo -> Novo -> Novo Projeto Flutter
5
Machine Translated by Google
Vibração
Etapa 3: selecione o aplicativo Flutter. Para isso, selecione Aplicativo Flutter e clique em Avançar.
6
Machine Translated by Google
Vibração
O Android Studio cria um aplicativo flutter totalmente funcional com funcionalidade mínima.
Vamos verificar a estrutura da aplicação e a seguir alterar o código para realizar nossa tarefa.
7
Machine Translated by Google
Vibração
8
Machine Translated by Google
Vibração
Etapa 7: Substitua o código dart no arquivo lib/ main.dart pelo código abaixo:
importar 'pacote:flutter/material.dart';
}
}
@override
Widget build(BuildContext context) { return Scaffold( appBar:
AppBar( title:
Text(this.title), ), body:
Center( child: Text( 'Hello World',
), );
}
}
• Linha 1: importa o pacote flutter, material. O material é um pacote flutter para criar uma interface de
usuário de acordo com as diretrizes de design de materiais especificadas pelo Android.
• Linha 3: Este é o ponto de entrada do aplicativo Flutter. Chama a função runApp e passa para ela
um objeto da classe MyApp . O objetivo da função runApp é anexar o widget fornecido à tela.
• Linha 5 - 17: Widget é usado para criar UI no framework flutter. StatelessWidget é um widget que
não mantém nenhum estado do widget. MyApp estende StatelessWidget e substitui seu método
de construção . O propósito da construção
9
Machine Translated by Google
Vibração
método é criar uma parte da UI do aplicativo. Aqui, o método build usa MaterialApp, um widget para criar a UI de
nível raiz do aplicativo. Possui três propriedades – título, tema e página inicial.
o tema é o tema do widget. Aqui, definimos azul como a cor geral do aplicativo usando a classe ThemeData
e sua propriedade, PrimarySwatch.
tela.
10
Machine Translated by Google
Vibração
11
Machine Translated by Google
Widgets
O conceito central da estrutura Flutter é No Flutter, tudo é um widget. Widgets são basicamente
componentes de interface de usuário usados para criar a interface de usuário do aplicativo.
Por exemplo, a hierarquia de widgets do aplicativo hello world (criada no capítulo anterior) é
especificada no diagrama a seguir:
12
Machine Translated by Google
Vibração
• MyApp é o widget criado pelo usuário e é construído usando o widget nativo do Flutter,
MaterialApp.
• MaterialApp possui uma propriedade home para especificar a interface do usuário da página inicial,
que é novamente um widget criado pelo usuário, MyHomePage.
• body é usado para especificar sua interface de usuário principal e appBar é usado para especificar seu cabeçalho
interface de usuário.
• Header UI é construído usando widget nativo flutter, AppBar e Body UI são construídos usando
Widget central .
• O widget Center possui uma propriedade, Child, que se refere ao conteúdo real e é construída usando o widget Text .
Gestos
Os widgets Flutter suportam interação por meio de um widget especial, GestureDetector.
GestureDetector é um widget invisível que tem a capacidade de capturar interações do usuário, como tocar, arrastar, etc.,
de seu widget filho. Muitos widgets nativos do Flutter suportam interação por meio do uso do GestureDetector. Também
podemos incorporar recursos interativos ao widget existente, compondo-o com o widget GestureDetector . Aprenderemos os
gestos separadamente nos próximos capítulos.
Conceito de Estado
Os widgets Flutter oferecem suporte à manutenção do estado , fornecendo um widget especial, StatefulWidget.
O widget precisa ser derivado do widget StatefulWidget para oferecer suporte à manutenção do estado e todos os outros
widgets devem ser derivados do StatelessWidget. Os widgets Flutter são reativos no nativo. Isso é semelhante ao reactjs e
o StatefulWidget será renderizado automaticamente sempre que seu estado interno for alterado. A nova renderização é
otimizada encontrando a diferença entre a interface do usuário do widget antigo e o novo e renderizando apenas as
alterações necessárias.
Camadas
O conceito mais importante da estrutura Flutter é que a estrutura é agrupada em múltiplas categorias em termos de
complexidade e claramente organizada em camadas de complexidade decrescente. Uma camada é construída usando sua
camada de nível seguinte imediato. A camada superior é o widget específico para Android e iOS. A próxima camada contém
todos os widgets nativos flutuantes. A próxima camada é a camada de renderização , que é um componente de renderização
de baixo nível e renderiza tudo no aplicativo flutter. As camadas vão até o código específico da plataforma principal.
13
Machine Translated by Google
Vibração
• Recursos interativos podem ser incorporados sempre que necessário usando o GestureDetector
ferramenta.
• O estado de um widget pode ser mantido sempre que necessário usando StatefulWidget
ferramenta.
• Flutter oferece design em camadas para que qualquer camada possa ser programada dependendo
da complexidade da tarefa.
14
Machine Translated by Google
Dart é uma linguagem de programação de uso geral de código aberto. Ele foi originalmente desenvolvido pelo Google. Dart
é uma linguagem orientada a objetos com sintaxe estilo C. Ele suporta conceitos de programação como interfaces, classes,
ao contrário de outras linguagens de programação. O Dart não oferece suporte a arrays. As coleções Dart podem ser usadas
para replicar estruturas de dados, como matrizes, genéricos e digitação opcional.
vazio principal()
{
print("A linguagem Dart é fácil de aprender");
}
Dart usa a palavra-chave var para declarar a variável. A sintaxe de var é definida abaixo,
As palavras-chave final e const são usadas para declarar constantes. Eles são definidos conforme abaixo:
• Strings: Representa uma sequência de caracteres. Os valores de string são especificados entre aspas simples ou duplas.
• Booleanos: o Dart usa a palavra-chave bool para representar valores booleanos – verdadeiro e falso.
• Listas e Mapas: É usado para representar uma coleção de objetos. Uma lista simples pode ser definida conforme abaixo:
15
Machine Translated by Google
Vibração
• Dinâmico: Se o tipo de variável não estiver definido, então seu tipo padrão é dinâmico. O
O exemplo a seguir ilustra a variável de tipo dinâmico:
void main()
{ nome dinâmico = "Dart";
imprimir(nome);
}
Loops são usados para repetir um bloco de código até que uma condição específica seja atendida. Dart suporta
para, para..in , while e do..while loops.
void main()
{ for( var i = 1 ; i <= 10; i++ ) { if(i%2==0)
{
imprimir(eu);
}
}
}
Funções
Uma função é um grupo de instruções que juntas executam uma tarefa específica. Vamos dar uma olhada
uma função simples no Dart conforme mostrado aqui:
void main()
{ add(3,4);
}
c=a+b;
imprimir(c);
}
16
Machine Translated by Google
Vibração
Uma classe é um modelo para a criação de objetos. Uma definição de classe inclui o seguinte:
• Campos
• Getters e setters
• Construtores
• Funções
classe Funcionário {
Nome da sequência;
//método getter
String get emp_name {nome de
retorno;
}
//método setter
void set emp_name(String nome) { this.name =
nome;
}
//definição da função
resultado nulo()
{
imprimir(nome);
}
} void main() { //
criação do objeto
Funcionário emp = new Funcionário();
emp.name="funcionário1";
emp.result(); //chamada de função
}
17
Machine Translated by Google
Como aprendemos no capítulo anterior, widgets são tudo no framework Flutter. Já aprendemos como criar
novos widgets nos capítulos anteriores.
Neste capítulo, vamos entender o conceito real por trás da criação de widgets e os diferentes tipos de
widgets disponíveis no framework Flutter .
Vamos verificar o widget MyHomePage do aplicativo Hello World . O código para esta finalidade é fornecido
abaixo:
@sobrepor
Construção de widget (contexto BuildContext) {
retornar Andaime(
appBar: AppBar(
título: Texto (este.título),
),
corpo: Centro (
filho: Texto (
'Olá Mundo',
)),
);
}
}
Observe que o StatelessWidget requer apenas a construção de um único método para ser implementado em
sua classe derivada. O método build obtém o ambiente de contexto necessário para construir os widgets
através do parâmetro BuildContext e retorna o widget que ele constrói.
No código, usamos title como um dos argumentos do construtor e também usamos Key como outro
argumento. O título é usado para exibir o título e a chave é usada para identificar o widget no ambiente de
construção.
Aqui, o método build chama o método build do Scaffold, que por sua vez chama o método build
método de AppBar e Center para construir sua interface de usuário.
18
Machine Translated by Google
Vibração
No Flutter, os widgets podem ser agrupados em várias categorias com base em seus recursos, conforme listado abaixo:
• Widgets de layout
Os widgets específicos do Android são projetados de acordo com as diretrizes de design de materiais do sistema operacional
Android. Widgets específicos do Android são chamados de widgets de materiais.
Os widgets específicos do iOS são projetados de acordo com as Diretrizes de Interface Humana da Apple e são chamados
de widgets de Cupertino .
• Andaime
• AppBar
19
Machine Translated by Google
Vibração
• BottomNavigationBar
• TabBar
• TabBarView
• ListTile
• Botão elevado
• FloatingActionButton
• FlatButton
• IconButton
• Botão suspenso
• PopupMenuButton
• Barra de botões
• Campo de texto
• Caixa de seleção
• Rádio
• Trocar
• Controle deslizante
• SimpleDialog •
AlertDialog
• Botão Cupertino
• CupertinoPicker
• CupertinoDatePicker •
CupertinoTimerPicker
• CupertinoNavigationBar
• CupertinoTabBar
• CupertinoTabScaffold •
CupertinoTabView •
CupertinoTextField
• Diálogo Cupertino
• CupertinoDialogAction
• CupertinoFullscreenDialogTransition •
CupertinoPageScaffold
• CupertinoPageTransition
• CupertinoActionSheet
• CupertinoActivityIndicator •
CupertinoAlertDialog •
CupertinoPopupSurface
20
Machine Translated by Google
Vibração
• Cupertino Slider
Widgets de layout
No Flutter, um widget pode ser criado compondo um ou mais widgets. Para compor vários widgets em um único widget, o
Flutter fornece um grande número de widgets com recurso de layout. Por exemplo, o widget filho pode ser centralizado
usando o widget Central .
O widget derivado de StatelessWidget não possui nenhuma informação de estado, mas pode conter widget derivado de
StatefulWidget. A natureza dinâmica do aplicativo se dá por meio do comportamento interativo dos widgets e das mudanças
de estado durante a interação. Por exemplo, tocar em um botão de contador aumentará/diminuirá o estado interno do contador
em um e a natureza reativa do widget Flutter irá renderizar automaticamente o widget usando novas informações de estado.
Aprenderemos o conceito de widgets StatefulWidget em detalhes no próximo capítulo sobre gerenciamento de estado .
Texto
O widget de texto é usado para exibir um pedaço de string. O estilo da string pode ser definido usando a propriedade style e
a classe TextStyle . O código de exemplo para esta finalidade é o seguinte:
O widget de texto possui um construtor especial, Text.rich, que aceita o filho do tipo TextSpan
para especificar a string com estilo diferente. O widget TextSpan é de natureza recursiva e aceita TextSpan como seus filhos.
O código de exemplo para esta finalidade é o seguinte:
21
Machine Translated by Google
Vibração
• textAlign, TextAlign: Alinhamento do texto como direita, esquerda, justificar, etc., usando
Classe TextAlign
• textDirection, TextDirection: Direção do texto para fluir, da esquerda para a direita ou da direita
para a esquerda
Imagem
O widget de imagem é usado para exibir uma imagem no aplicativo. O widget de imagem fornece diferentes
construtores para carregar imagens de múltiplas fontes e são os seguintes:
A opção mais fácil de carregar e exibir uma imagem no Flutter é incluir a imagem como ativos do aplicativo e
carregá-la no widget sob demanda.
vibração:
ativos:
- ativos/smiley.png
Image.asset('assets/smiley.png')
22
Machine Translated by Google
Vibração
@override
Widget build (contexto BuildContext) { return
Scaffold( appBar:
AppBar( title:
Text(this.title), ), body:
Center( child:
Image.asset("assets/smiley.png")
), );
}
23
Machine Translated by Google
Vibração
Ícone
O widget de ícone é usado para exibir um glifo de uma fonte descrita na classe IconData . O código para carregar um ícone de e-
mail simples é o seguinte:
Ícone (Ícones.email)
@override
Widget build (contexto BuildContext) { return
Scaffold( appBar:
AppBar( title:
Text(this.title), ), body: Center( child:
Icon(Icons.email)
), );
}
}
24
Machine Translated by Google
Vibração
25
Machine Translated by Google
Como o conceito central do Flutter é Everything is widget, o Flutter incorpora uma funcionalidade de layout de
interface do usuário nos próprios widgets. O Flutter fornece vários widgets especialmente projetados, como
Container, Center, Align, etc., apenas com o propósito de definir o layout da interface do usuário. Widgets
construídos compondo outros widgets normalmente usam widgets de layout. Vamos aprender o conceito de
layout Flutter neste capítulo.
Tipo de LayoutWidgets
Os widgets de layout podem ser agrupados em duas categorias distintas com base em seu filho:
Por exemplo, o widget Center apenas centraliza o widget filho em relação ao widget pai e o widget Container
fornece flexibilidade completa para colocá-lo filho em qualquer lugar dentro dele usando diferentes opções como
preenchimento, decoração, etc.,
Widgets filho único são ótimas opções para criar widgets de alta qualidade com funcionalidade única, como
botão, rótulo, etc.,
@sobrepor
Construção de widget (contexto BuildContext) {
retornar contêiner (
decoração: const BoxDecoration(
fronteira: Fronteira(
topo: BorderSide (largura: 1,0, cor: Color (0xFFFFFFFFFF)),
esquerda: BorderSide (largura: 1,0, cor: Color (0xFFFFFFFFFF)),
direita: BorderSide (largura: 1,0, cor: Color (0xFFFF000000)),
inferior: BorderSide (largura: 1,0, cor: Color (0xFFFF000000)),
),
),
filho: Contêiner (
preenchimento: const EdgeInsets.simetric (horizontal: 20,0, vertical: 2,0),
decoração: const BoxDecoration(
fronteira: Fronteira(
topo: BorderSide (largura: 1,0, cor: Color (0xFFFFDFDFDF)),
26
Machine Translated by Google
Vibração
Aqui, usamos dois widgets – um widget Container e um widget Text . O resultado do widget é um botão personalizado
conforme mostrado abaixo:
Vamos verificar alguns dos widgets de layout filho único mais importantes fornecidos pelo Flutter:
• Preenchimento: Usado para organizar seu widget filho de acordo com o preenchimento fornecido. Aqui, o preenchimento
pode ser fornecido pela classe EdgeInsets .
• Alinhar: Alinhe seu widget filho dentro de si mesmo usando o valor da propriedade de alinhamento . O valor da propriedade
de alinhamento pode ser fornecido pela classe FractionalOffset . A classe FractionalOffset especifica os deslocamentos
em termos de distância do canto superior esquerdo.
Centro(
filho: Contêiner (
altura: 100,0,
largura: 100,0,
cor: Cores. amarelo,
filho: Alinhar (
alinhamento: FractionalOffset (0,2, 0,6),
filho: Contêiner (
altura: 40,0,
largura: 40,0,
cor: Cores.vermelho,
),
),
),
)
27
Machine Translated by Google
Vibração
• ConstrainedBox
• Linha de base
• FractinallySizedBox
• Altura Intrínseca
• Largura Intrínseca
• Caixa Limitada
• Fora do palco
• OverflowBox
• SizedBox
• SizedOverflowBox
• Transformar
• CustomSingleChildLayout
Nosso aplicativo Hello World usa widgets de layout baseados em materiais para projetar a página inicial.
Vamos modificar nosso aplicativo hello world para construir a página inicial usando widgets de layout básicos
conforme especificado abaixo:
• Contêiner: Widget de contêiner genérico, filho único, baseado em caixa, com alinhamento,
preenchimento, borda e margem, além de recursos avançados de estilo.
• Centro: Widget de contêiner filho simples e único, que centraliza seu widget filho.
}
}
@sobrepor
28
Machine Translated by Google
Vibração
cor: Cores.branco,
),
preenchimento: EdgeInsets.all(25),
Texto(
'Olá Mundo',
estilo: EstiloTexto(
cor: Cores.preto,
),
textDirection: TextDirection.ltr,
),
));
Aqui,
• Widget de contêiner é o widget de nível superior ou raiz. O contêiner é configurado usando propriedades
de decoração e preenchimento para fazer o layout de seu conteúdo.
• BoxDecoration possui muitas propriedades como cor, borda, etc., para decorar o Container
widget e aqui, color é usado para definir a cor do contêiner.
• o preenchimento do widget Container é definido usando a classe dgeInsets , que fornece a opção de especificar
o valor do preenchimento.
• Center é o widget filho do widget Container . Novamente, Text é filho do widget Center . Text é usado para
mostrar a mensagem e Center é usado para centralizar a mensagem de texto em relação ao widget pai,
Container.
29
Machine Translated by Google
Vibração
O resultado final do código fornecido acima é um exemplo de layout conforme mostrado abaixo:
Por exemplo, o widget Row permite o layout de seus filhos na direção horizontal, enquanto o widget Coluna
permite o layout de seus filhos na direção vertical. Ao compor Linha e Coluna, widgets com qualquer nível de
complexidade podem ser construídos.
Vamos aprender alguns dos widgets usados com frequência nesta seção.
• Expandido - Usado para fazer com que os filhos do widget Linha e Coluna ocupem o
área máxima possível.
30
Machine Translated by Google
Vibração
importar 'pacote:flutter/material.dart';
@sobrepor
Construção de widget (contexto BuildContext)
{ return Scaffold (
appBar: AppBar(título:
Texto(este.título),), corpo: Centro(filho:
Texto(
'Olá Mundo', )),
);
}
}
31
Machine Translated by Google
Vibração
• Aqui,
• Agora, crie um novo widget, ProductBox de acordo com o design especificado conforme mostrado
abaixo:
EdgeInsets.all(5), child:
Column( mainAxisAlignment:
Text(this.description), Text("Preço:
" + this.price.toString()), ], )))
]))); }
}
32
Machine Translated by Google
Vibração
o Contêiner
o Expandido
o Linha
o Coluna
o Cartão
o Texto
o Imagem
33
Machine Translated by Google
Vibração
• ProductBox foi projetado usando o widget mencionado acima. A organização ou hierarquia do widget é
especificada no diagrama mostrado abaixo:
• Agora, coloque alguma imagem fictícia (veja abaixo) para informações do produto na pasta de ativos do aplicativo e
configure a pasta de ativos no arquivo pubspec.yaml conforme mostrado abaixo:
ativos:
- assets/appimages/floppy.png - assets/
appimages/iphone.png - assets/appimages/
laptop.png - assets/appimages/pendrive.png
- assets/appimages/pixel.png - assets/
appimages/tablet.png
iPhone.png
34
Machine Translated by Google
Vibração
Pixel.png
Laptop.png
Tablet.png
Pendrive.png
Disquete.png
• Finalmente, use o widget ProductBox no widget MyHomePage conforme especificado abaixo:
@sobrepor
Compilação de widget (contexto BuildContext)
{ return
Scaffold( appBar: AppBar(title: Text("Listagem de produtos")),
body:
ListView( ShrinkWrap: true,
35
Machine Translated by Google
Vibração
ProductBox( nome:
"Pixel", descrição: "Pixel é o telefone com mais recursos de todos os
tempos",
preço: 800, imagem:
"pixel.png"),
ProductBox( nome:
"Laptop", descrição: "Laptop é a ferramenta de desenvolvimento mais produtiva
", preço: 2000,
imagem: "laptop.png"),
ProductBox( name:
"Tablet", description: "Tablet é o dispositivo mais útil de todos os tempos para
reunião",
preço: 1500,
imagem: "tablet.png"),
ProductBox( nome:
"Pendrive", descrição: "Pendrive é um meio de armazenamento
útil", preço:
100, imagem: "pendrive.png"),
ProductBox(
nome: "Unidade de disquete",
descrição: "A unidade de disquete é um meio de armazenamento de resgate útil",
preço: 20,
imagem: "floppy.png"),
], ));
}
}
importar 'pacote:flutter/material.dart';
36
Machine Translated by Google
Vibração
),
home: MyHomePage(title: 'Página inicial de demonstração de layout do produto'), );
}
}
@override
Widget build (contexto BuildContext) { return
Scaffold( appBar:
AppBar(title: Text("Listagem de produtos")), body:
ListView( ShrinkWrap:
true, padding: const
EdgeInsets.fromLTRB(2.0, 10.0, 2.0, 10.0) , filhos: <Widget>[ ProductBox( nome:
"iPhone", descrição:
"iPhone é o
telefone estilista de
todos os tempos", preço: 1000, imagem: "iphone.png"),
ProductBox( nome:
"Pixel", descrição: "Pixel é o telefone com mais recursos de todos os tempos",
preço: 800,
imagem: "pixel.png"),
ProductBox( nome:
"Laptop", descrição: "Laptop é a ferramenta de desenvolvimento mais produtiva
", preço: 2000,
imagem: "laptop.png"),
ProductBox( name:
"Tablet", description: "Tablet é o dispositivo mais útil de todos os tempos para
reunião",
preço: 1500,
imagem: "tablet.png"),
ProductBox( nome:
"Pendrive", descrição: "Pendrive é um meio de armazenamento útil",
preço: 100,
imagem: "pendrive.png"),
ProductBox(
nome: "Unidade de disquete",
descrição: "A unidade de disquete é um meio de armazenamento de resgate útil",
preço: 20,
imagem: "floppy.png"),
], ));
}
}
37
Machine Translated by Google
Vibração
Expanded( child:
Container( padding: EdgeInsets.all(5),
child:
Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children:
])));
}
}
38
Machine Translated by Google
Vibração
39
Machine Translated by Google
Os gestos são principalmente uma forma de um usuário interagir com um aplicativo móvel (ou qualquer
dispositivo baseado em toque). Gestos são geralmente definidos como qualquer ação/movimento físico de
um usuário na intenção de ativar um controle específico do dispositivo móvel. Os gestos vão desde tocar
na tela do dispositivo móvel até ações mais complexas usadas em aplicativos de jogos.
• Toque: Tocar a superfície do dispositivo com a ponta do dedo por um curto período e depois
liberando a ponta do dedo.
• Arrastar: Tocar a superfície do dispositivo com a ponta do dedo e depois mover a ponta do dedo de
maneira constante e finalmente soltar a ponta do dedo.
• Panorâmica: Tocar a superfície do dispositivo com a ponta do dedo e movê-lo em qualquer direção
sem soltar a ponta do dedo.
Flutter oferece um excelente suporte para todos os tipos de gestos através de seu widget exclusivo,
GestureDetector. GestureDetector é um widget não visual usado principalmente para detectar o gesto do
usuário. Para identificar um gesto direcionado a um widget, o widget pode ser colocado dentro do widget
GestureDetector. O GestureDetector irá capturar o gesto e enviar vários eventos com base no gesto.
• Toque
o onTapDown
o onTapUp
o onTap
o onTapCancel
o onDoubleTap
• Pressão longa
o onLongPress
40
Machine Translated by Google
Vibração
• Arrastar verticalmente
o onVerticalDragStart
o onVerticalDragUpdate
oonVerticalDragEnd
• Arrastar horizontalmente
o onHorizontalDragStart
o onHorizontalDragUpdate
o onHorizontalDragEnd
• Panela
o onPanStart
o onPanUpdate
o onPanEnd
Agora, vamos modificar o aplicativo hello world para incluir o recurso de detecção de gestos e tentar entender o conceito.
{ _showDialog(context);
},
filho: Texto(
'Olá Mundo',
)
)
),
• Implemente a função *_showDialog* para apresentar uma caixa de diálogo quando o usuário tabula a mensagem hello
world . Ele usa os widgets showDialog e AlertDialog genéricos para criar um novo widget de diálogo. O código
é mostrado abaixo:
41
Machine Translated by Google
Vibração
of(contexto).pop(); }, ), ], ); }, ); }
• O aplicativo será recarregado no dispositivo usando o recurso Hot Reload . Agora, basta clicar na mensagem Hello World
e aparecerá a caixa de diálogo abaixo:
42
Machine Translated by Google
Vibração
importar 'pacote:flutter/material.dart';
}
}
Navigator.of(context).pop(); }, ), ], ); }, );
@override
Widget build (contexto BuildContext) { return
Scaffold( appBar:
AppBar( title:
Text(this.title), ),
43
Machine Translated by Google
Vibração
{ _showDialog(context); }, filho:
Text(
'Olá Mundo', ))),
);
}
}
Finalmente, o Flutter também fornece um mecanismo de detecção de gestos de baixo nível por meio do widget Listener . Ele
detectará todas as interações do usuário e então despachará os seguintes eventos:
• Evento PointerDown
• PointerMoveEvent
• PointerUpEvent
• PointerCancelEvent
O Flutter também fornece um pequeno conjunto de widgets para realizar gestos específicos e avançados.
Os widgets estão listados abaixo:
• LongPressDraggable: Suporta gesto de arrastar para mover um widget, quando seu pai
widget também pode ser arrastado.
• AbsorbPointer: interrompe o próprio processo de detecção de gestos e, portanto, qualquer widget sobreposto também
não poderá participar do processo de detecção de gestos e, portanto, nenhum evento será gerado.
44
Machine Translated by Google
Vibração
9. Flutter – Gestão do Estado
Gerenciar o estado de um aplicativo é um dos processos mais importantes e necessários no ciclo de vida de um aplicativo.
• Depois que o usuário estiver logado, o aplicativo deverá persistir os detalhes do usuário logado em todos
a tela.
• Novamente, quando o usuário seleciona um produto e o salva em um carrinho, as informações do carrinho devem
persistir entre as páginas até que o usuário faça check-out do carrinho.
• As informações do usuário e de seu carrinho em qualquer instância são chamadas de estado do aplicativo
naquela instância.
Um gerenciamento de estado pode ser dividido em duas categorias com base na duração que o estado específico dura em
um aplicativo.
• Efêmero - Dura alguns segundos, como o estado atual de uma animação, ou uma única página, como a classificação
atual de um produto. Flutter oferece suporte por meio do StatefulWidget.
• estado do aplicativo - último para todo o aplicativo, como detalhes do usuário conectado, informações do carrinho,
etc., o Flutter oferece suporte por meio de scoped_model.
Vamos criar um widget, RatingBox com manutenção de estado. O objetivo do widget é mostrar a classificação atual de um
produto específico. O processo passo a passo para criar um widget RatingBox com manutenção de estado é o seguinte:
45
Machine Translated by Google
Vibração
return
Row( mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end, mainAxisSize:
MainAxisSize.max, filhos:
IconButton(
IconButton(
], );
}
46
Machine Translated by Google
Vibração
Aqui, usamos três estrelas, criadas usando o widget IconButton e organizadas usando o widget Row em uma única linha. A ideia
é mostrar a classificação através da sequência de estrelas vermelhas.
Por exemplo, se a classificação for de duas estrelas, as duas primeiras estrelas serão vermelhas e a última será branca.
void _setRatingAsTwo() {
setState( ()
{ _classificação =
2; });
}
• Aqui, cada método define a classificação atual do widget por meio de setState
return
Row( mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end, mainAxisSize:
MainAxisSize.max, filhos:
IconButton(
47
Machine Translated by Google
Vibração
], );
}
Aqui, o evento onPressed chama a função relevante para alterar o estado e posteriormente alterar a interface do usuário. Por
exemplo, se um usuário clicar na terceira estrela, _setRatingAsThree será chamado e mudará _rating para 3. Como o estado foi
alterado, o método build será chamado novamente e a interface do usuário será construída e renderizada novamente.
void _setRatingAsTwo() {
setState( ()
{ _classificação =
2; });
}
48
Machine Translated by Google
Vibração
return
Row( mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end, mainAxisSize:
MainAxisSize.max, filhos:
IconButton(
IconButton(
], );
}
}
Vamos criar um novo aplicativo e usar nosso widget RatingBox recém-criado para mostrar a classificação do produto.
importar 'pacote:flutter/material.dart';
49
Machine Translated by Google
Vibração
@override
Widget build (contexto BuildContext) { return Scaffold( appBar:
AppBar( title:
Text(this.title), ), body:
Center( child:
Texto(
'Olá Mundo', )),
);
}
}
• Aqui,
• Crie um widget ProductBox para listar o produto junto com a classificação conforme especificado abaixo:
50
Machine Translated by Google
Vibração
preenchimento: EdgeInsets.all(2),
altura: 120, filho:
Card( filho: Row(
Expanded( child:
Container( padding: EdgeInsets.all(5),
child:
Column( mainAxisAlignment:
MainAxisAlignment.spaceEvenly,
filhos:
])));
}
}
@override
Widget build (contexto BuildContext) { return
Scaffold( appBar:
AppBar(title: Text("Listagem de produtos")), body:
ListView( ShrinkWrap:
true, padding: const
EdgeInsets.fromLTRB(2.0, 10.0, 2.0, 10.0) , filhos: <Widget>[ ProductBox( nome:
"iPhone", descrição:
"iPhone é o
telefone estilista de
todos os tempos", preço: 1000, imagem: "iphone.png"),
ProductBox( nome:
"Pixel", descrição: " Pixel é
o telefone com
mais recursos de
todos os tempos", preço: 800, imagem: "pixel.png"), ProductBox( nome:
"Laptop",
descrição: "Laptop é a
ferramenta de
desenvolvimento
mais produtiva",
51
Machine Translated by Google
Vibração
preço: 2000,
imagem: "laptop.png"),
ProductBox( name:
"Tablet", description: "Tablet é o dispositivo mais útil de todos os tempos para
reunião",
preço: 1500,
imagem: "tablet.png"),
ProductBox( nome:
"Pendrive", descrição: "Pendrive é um meio de armazenamento
útil", preço:
100, imagem: "pendrive.png"),
ProdutoCaixa(
name: "Unidade de disquete",
description: "A unidade de disquete é um armazenamento de resgate útil
médio",
preço: 20,
imagem: "floppy.png"),
], ));
}
}
importar 'pacote:flutter/material.dart';
@sobrepor
Compilação de widget (contexto BuildContext)
{ return
Scaffold( appBar: AppBar(title: Text("Listagem de produtos")),
body: ListView(
52
Machine Translated by Google
Vibração
ShrinkWrap: true,
preenchimento: const EdgeInsets.fromLTRB(2.0, 10.0, 2.0, 10.0), filhos:
<Widget>[ ProductBox( nome:
"iPhone",
descrição: "iPhone
é o telefone estilista de todos os tempos", preço: 1000, imagem :
"iphone.png"),
ProductBox( nome:
"Pixel", descrição: "Pixel é o telefone com mais recursos de todos os
tempos",
preço: 800, imagem:
"pixel.png"),
ProductBox( nome:
"Laptop", descrição: "Laptop é a ferramenta de desenvolvimento mais produtiva
", preço: 2000,
imagem: "laptop.png"),
ProductBox( name:
"Tablet", description: "Tablet é o dispositivo mais útil de todos os tempos para
reunião",
preço: 1500,
imagem: "tablet.png"),
ProductBox( nome:
"Pendrive", descrição: "iPhone é o telefone estilista de todos os
tempos",
preço: 100, imagem:
"pendrive.png"), ProductBox(
nome: "Floppy Drive",
descrição: "iPhone é o telefone estilista de todos os tempos",
preço: 20,
imagem: "floppy.png"),
ProductBox(nome:
"iPhone", descrição: "iPhone é o telefone estilista de todos os
tempos", preço:
1000, imagem: "iphone.png"),
ProductBox(nome:
"iPhone", descrição: "iPhone é o telefone estilista de todos os
tempos", preço:
1000, imagem: "iphone.png"),
], ));
}
}
53
Machine Translated by Google
Vibração
int _classificação = 0;
void _setRatingAsTwo() {
setState( ()
{ _classificação =
2; });
}
return
Row( mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end, mainAxisSize:
MainAxisSize.max, filhos:
IconButton(
IconButton(
54
Machine Translated by Google
Vibração
color: Colors.red[500],
onPressed: _setRatingAsThree,
iconSize: _size, ), ),
], );
}
}
Expanded( child:
Container( padding: EdgeInsets.all(5),
child:
Column( mainAxisAlignment:
MainAxisAlignment.spaceEvenly,
filhos:
])));
}
}
55
Machine Translated by Google
Vibração
• Por fim, execute o aplicativo e consulte a página Gerenciamento de estado - Lista de produtos
Resultados conforme mostrado aqui:
56
Machine Translated by Google
Vibração
Clicar na estrela de avaliação atualizará a avaliação do produto. Por exemplo, definir 2 estrelas
a classificação para iPhone exibirá a classificação conforme abaixo:
scoped_model fornece três classes principais para permitir o gerenciamento robusto de estado em um
aplicativo, que são discutidas em detalhes aqui:
Modelo
O modelo encapsula o estado de um aplicativo. Podemos usar quantos Model (herdando a classe Model)
forem necessários para manter o estado do aplicativo. Possui um único método, notifyListeners, que precisa
ser chamado sempre que o estado do Model muda. notifyListeners fará as coisas necessárias para atualizar
a IU.
57
Machine Translated by Google
Vibração
notificarListeners();
}
}
ScopedModel é um widget que contém o modelo fornecido e o passa para todos os widgets descendentes, se
solicitado. Se for necessário mais de um modelo, precisaremos aninhar o ScopedModel.
• Modelo único
ScopedModel<Produto>( modelo:
item, filho:
AnyWidget()
)
• Modelo múltiplo
ScopedModel<Produto>( modelo:
item1, filho:
ScopedModel<Produto>( modelo:
item2, filho:
AnyWidget(), ),
ScopedModel.of é um método usado para obter o modelo subjacente ao ScopedModel. Ele pode ser usado
quando nenhuma alteração na interface do usuário for necessária, mesmo que o modelo seja alterado. O
seguinte não alterará a UI (classificação) do produto.
ScopedModel.of<Produto>(context).updateRating(2);
58
Machine Translated by Google
Vibração
ScopedModelDescendente
ScopedModelDescendant é um widget que obtém o modelo do widget de nível superior, ScopedModel, e constrói sua
interface de usuário sempre que o modelo muda.
ScopedModelDescendant tem duas propriedades – construtor e filho. child é a parte da UI que não muda e será
passada para o construtor. construtor aceita uma função com três argumentos:
• filho - Uma parte da UI, que não muda com base no modelo.
• model - O modelo real naquela instância.
return ScopedModelDescendant<ProductModel>(
construtor: (contexto, filho, carrinho) => { ... UI real ... }, filho: PartOfTheUI(), );
Vamos alterar nosso exemplo anterior para usar scoped_model em vez de StatefulWidget
vibração:
ativos:
- assets/appimages/floppy.png - assets/
appimages/iphone.png - assets/appimages/
laptop.png - assets/appimages/pendrive.png
- assets/appimages/pixel.png - assets/
appimages/tablet.png
dependências:
modelo_com escopo: ^1.0.1
• Clique na opção Obter dependências. O Android Studio obterá o pacote da Internet e o configurará
adequadamente para o aplicativo.
59
Machine Translated by Google
Vibração
importar 'pacote:flutter/material.dart';
@override
Widget build (contexto BuildContext) { return Scaffold( appBar:
AppBar( title:
Text(this.title), ), body:
Center( child: Text( 'Hello World', )),
);
}
}
importar 'pacote:scoped_model/scoped_model.dart';
• Vamos criar uma classe Product, Product.dart para organizar as informações do produto.
importar 'pacote:scoped_model/scoped_model.dart';
60
Machine Translated by Google
Vibração
notificarListeners();
}
}
• Vamos escrever um método getProducts na classe Product para gerar nosso modelo
registros do produto.
items.add(Product( "Pixel",
"Pixel é o
telefone com mais recursos de todos os tempos", 800,
"pixel.png", 0));
items.add(Product( "Laptop",
"Laptop é a
ferramenta de desenvolvimento mais produtiva", 2000,
"laptop.png", 0));
items.add(Product( "Tablet",
"Tablet é o
dispositivo mais útil para reuniões", 1500, "tablet.png", 0));
items.add(Product( "Pendrive",
"Pendrive é um
meio de armazenamento útil", 100, "pendrive.png",
0));
itens.add(Produto(
61
Machine Translated by Google
Vibração
"Unidade de disquete",
"Unidade de disquete é um meio de armazenamento de resgate útil", 20,
"floppy.png", 0));
devolver itens;
}
importar 'Produto.dart';
• Vamos mudar nosso novo widget, RatingBox, para suportar o conceito scoped_model.
return
Row( mainAxisAlignment: MainAxisAlignment.end, crossAxisAlignment:
CrossAxisAlignment.end, mainAxisSize: MainAxisSize.max, filhos:
<Widget>[ Container( preenchimento: EdgeInsets.all(0),
filho: IconButton( ícone:
(item.rating >= 1?
Ícone( Icons.star, tamanho: _size,
)
:
Icon( Icons.star_border, size:
_size, )), color:
EdgeInsets.all(0),
filho: IconButton( ícone: (item.rating >=
2 ? Icon( Icons.star,
tamanho: _size,
)
: Ícone
( Icons.star_border,
tamanho: _size,
62
Machine Translated by Google
Vibração
)),
cor: Colors.red[500], onPressed: () =>
this.item.updateRating(2), iconSize: _size, ), ), Container( preenchimento:
EdgeInsets.all(0), filho:
IconButton( ícone:
(item.rating >= 3 ? Ícone( Icons.star, tamanho:
_size,
)
:
Icon( Icons.star_border,
size: _size, )),
color: Colors.red[500],
onPressed: () => this.item.updateRating(3), iconSize:
_size, ), ), ], );
}
}
• Vamos modificar nosso widget ProductBox para funcionar com Product, ScopedModel e
Classe ScopedModelDescendant.
EdgeInsets.all(5), child:
ScopedModel<Product >( modelo:
este.item, filho: Coluna (
63
Machine Translated by Google
Vibração
mainAxisAlignment:
MainAxisAlignment.spaceEvenly, filhos:
<Widget>[
Text(este.item.nome,
estilo:
TextStyle(fontWeight:
Intensidade da fonte: Negrito)),
Text(este.item.descrição), Text("Preço:
" +
este.item.preço.toString()),
ScopedModelDescendant<Produto>(
construtor: (contexto, filho, item) {
return RatingBox(item: item); }) ], ))))
]),
));
}
}
@override
Widget build(BuildContext context) { return
Scaffold( appBar:
AppBar(title: Text("Navegação do Produto")), body: ListView.builder(
itemCount: itens.length,
itemBuilder: (contexto, índice) { return
ProductBox(item: itens[índice]); }, ));
}
}
Produto.dart
importar 'pacote:scoped_model/scoped_model.dart';
64
Machine Translated by Google
Vibração
nulo cn
"Laptop é a ferramenta de desenvolvimento mais produtiva",
2000,
"laptop.png", 0));
items.add(Product( "Pendrive",
"Pendrive é um
meio de armazenamento útil", 100, "pendrive.png",
0));
items.add(Product( "Floppy
Drive", "Floppy Drive
é um meio de armazenamento de resgate útil", 20, "floppy.png", 0));
devolver itens;
}
}
principal.dart
65
Machine Translated by Google
Vibração
@sobrepor
Construção de widget (contexto BuildContext) {
return MaterialApp (título:
'Flutter Demo', tema: ThemeData
(primarySwatch:
Colors.blue, ), home: MyHomePage
}
}
@override
Widget build(BuildContext context) { return
Scaffold( appBar:
AppBar(title: Text("Navegação do Produto")), body: ListView.builder(
}
}
return
Row( mainAxisAlignment: MainAxisAlignment.end, crossAxisAlignment:
CrossAxisAlignment.end, mainAxisSize: MainAxisSize.max, filhos:
<Widget>[ Container( preenchimento: EdgeInsets.all(0),
filho: IconButton( ícone:
(item.rating >= 1?
Ícone( Icons.star, tamanho: _size,
)
: Ícone (
66
Machine Translated by Google
Vibração
Icons.star_border,
tamanho:
EdgeInsets.all
(0), filho: IconButton( ícone: (item.rating
>= 2 ? Icon( Icons.star,
tamanho: _size,
)
:
Icon( Icons.star_border, size:
_size, )), color:
Colors.red[500], onPressed: ()
=> this.item.updateRating(2), iconSize: _size, ), ),
Container( preenchimento:
)
:
Icon( Icons.star_border, size:
_size, )), color:
Colors.red[500], onPressed: ()
=> this.item.updateRating(3), iconSize: _size, ), ), ], );
}
}
67
Machine Translated by Google
Vibração
altura: 140,
filho: Cartão
(filho: Linha (
mainAxisAlignment: MainAxisAlignment.spaceEvenly, filhos:
<Widget>[ Image.asset("assets/
appimages/" + this.item.image), Expanded( child: Container( padding:
EdgeInsets.all(5), child:
ScopedModel<Product >(modelo:
this.item, filho:
Column( mainAxisAlignment:
MainAxisAlignment.spaceEvenly, filhos:
<Widget>[
Text(este.item.nome, estilo:
TextStyle(fontWeight:
Intensidade da fonte: Negrito)),
Text(este.item.descrição), Text("Preço:
" +
este.item.preço.toString()),
ScopedModelDescendant<Produto>(
construtor: (contexto, filho, item) {
return RatingBox(item: item); }) ], ))))
]),
));
}
}
Por fim, compile e execute o aplicativo para ver seu resultado. Funcionará de forma semelhante ao exemplo
anterior, exceto que o aplicativo usa o conceito scoped_model.
Navegação e roteamento
Em qualquer aplicação, navegar de uma página/tela para outra define o fluxo de trabalho da aplicação. A forma
como a navegação de uma aplicação é tratada é chamada de Roteamento.
Flutter fornece uma classe de roteamento básica – MaterialPageRoute e dois métodos – Navigator.push e
Navigator.pop, para definir o fluxo de trabalho de uma aplicação.
MaterialPageRoute
MaterialPageRoute é um widget usado para renderizar sua UI, substituindo a tela inteira por uma animação
específica da plataforma.
Aqui, o construtor aceitará uma função para construir seu conteúdo, suprindo o contexto atual do aplicativo.
Navegação.push
68
Machine Translated by Google
Vibração
Navigation.push é usado para navegar para uma nova tela usando o widget MaterialPageRoute.
Navigator.push(contexto,
Navegação.pop
Navigation.pop é usado para navegar para a tela anterior.
Navigator.push(contexto);
vibração:
ativos:
- assets/appimages/floppy.png - assets/
appimages/iphone.png - assets/appimages/
laptop.png - assets/appimages/
pendrive.png - assets/appimages/pixel.png -
assets/appimages/tablet.png
importar 'pacote:flutter/material.dart';
}
}
69
Machine Translated by Google
Vibração
@override
Widget build (contexto BuildContext) { return Scaffold( appBar:
AppBar( title:
Text(this.title), ), body:
Center( child: Text( 'Hello World', )),
);
}
}
• Vamos escrever um método getProducts na classe Product para gerar nosso modelo
registros do produto.
items.add(Product( "Pixel",
"Pixel é o
telefone com mais recursos de todos os tempos", 800,
"pixel.png"));
items.add(Product( "Laptop",
"Laptop é a
ferramenta de desenvolvimento mais produtiva", 2000,
"laptop.png"));
items.add(Product( "Tablet",
"Tablet é o
dispositivo mais útil para reuniões", 1500, "tablet.png"));
items.add(Product( "Pendrive",
"Pendrive é um
meio de armazenamento útil",
70
Machine Translated by Google
Vibração
100,
"pendrive.png"));
items.add(Product( "Floppy
Drive", "Floppy Drive
é um meio de armazenamento de resgate útil", 20, "floppy.png"));
devolver itens;
}
importar 'Produto.dart';
void _setRatingAsThree() {
setState(()
{ _classificação
= 3; });
}
return
Row( mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end, mainAxisSize:
MainAxisSize.max, filhos:
71
Machine Translated by Google
Vibração
(Ícones.estrela, tamanho:
_tamanho,
)
:
Icon( Icons.star_border, tamanho:
_size, )), cor:
Colors.red[500], onPressed:
_setRatingAsOne, iconSize: _size, ), ),
Container( preenchimento:
EdgeInsets.all(0),
filho: IconButton(
(Ícones.estrela, tamanho:
_tamanho,
)
: Ícone
( Icons.star_border,
tamanho: _size, )),
cor:
Colors.red [500], onPressed:
_setRatingAsTwo, iconSize: _size, ), ),
Container ( preenchimento:
EdgeInsets.all
(0), filho: IconButton (
(Ícones.estrela, tamanho:
_tamanho,
)
:
Icon( Icons.star_border, size:
_size, )), color:
Colors.red[500], onPressed:
_setRatingAsThree, iconSize: _size, ), ), ], );
}
}
72
Machine Translated by Google
Vibração
• Vamos modificar nosso widget ProductBox para funcionar com nossa nova classe Product.
Expanded( child:
Container( padding: EdgeInsets.all(5),
child:
]),
));
}
}
• Vamos reescrever nosso widget MyHomePage para funcionar com o modelo Product e listar todos os
produtos usando ListView.
@override
Widget build(BuildContext context) { return
Scaffold( appBar:
AppBar(title: Text("Navegação do Produto")), body: ListView.builder(
itemCount: itens.length,
itemBuilder: (contexto, índice) {
73
Machine Translated by Google
Vibração
{ Navigator.push( context,
MaterialPageRoute(
construtor: (contexto) => ProductPage(item:
itens[índice]),
), ); }, ); }, ));
}
}
@override
Widget build (contexto BuildContext) { return
Scaffold( appBar:
AppBar( title:
Text(this.item.name), ), body:
Center( child:
Container( padding:
EdgeInsets.all(0),
filho: Coluna
(mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start, filhos:
<Widget>[ Image.asset("assets/
appimages/" +
este.item.imagem),
Expandido( filho:
Container( preenchimento:
EdgeInsets.all(5),
filho: Coluna( mainAxisAlignment:
MainAxisAlignment.spaceEvenly,
filhos: <Widget>[
Text(este.item.nome, estilo:
TextStyle(fontWeight:
Intensidade da fonte: Negrito)),
Text(este.item.descrição), Text("Preço: "
+
este.item.preço.toString()),
RatingBox(),
74
Machine Translated by Google
Vibração
], )))
]),
),
), );
}
}
importar 'pacote:flutter/material.dart';
items.add(Product( "Pixel",
"Pixel é o telefone com mais recursos de todos os tempos", 800,
"pixel.png"));
2000, "laptop.png"));
items.add(Product( "Tablet",
"Tablet é o
dispositivo mais útil para reuniões", 1500, "tablet.png"));
items.add(Product( "Pendrive",
"iPhone é o telefone estilista de todos os tempos", 100, "pendrive.png"));
items.add(Product( "Floppy
Drive", "iPhone é o telefone estilista de todos os tempos", 20, "floppy.png"));
items.add(Product( "iPhone",
"iPhone é o telefone estilista de todos os tempos", 1000, "iphone.png"));
devolver itens;
}
}
75
Machine Translated by Google
Vibração
}
}
@override
Widget build(BuildContext context) { return
Scaffold( appBar:
AppBar(title: Text("Navegação do Produto")), body: ListView.builder(
itemCount: items.length,
itemBuilder: (contexto, índice) { return
GestureDetector( filho:
ProductBox(item: itens[índice]), onTap: ()
{ Navigator.push( context,
MaterialPageRoute(
construtor: (contexto) => ProductPage(item:
itens[índice]),
), ); }, ); }, ));
}
}
@sobrepor
Construção de widget (contexto BuildContext)
{ return Scaffold( appBar:
AppBar(
76
Machine Translated by Google
Vibração
corpo: Center
(filho: Container
(preenchimento: EdgeInsets.all (0),
filho: Column
(mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start, filhos:
<Widget
>[ Image.asset("assets/appimages/" + this.item.image),
Expanded( child:
Container( padding: EdgeInsets.all(5),
child:
Column( mainAxisAlignment:
MainAxisAlignment.spaceEvenly,
filhos: <Widget>[
Text(este.item.nome,
estilo: TextStyle(fontWeight:
Intensidade da fonte: Negrito)),
Text(este.item.descrição), Text("Preço:
" +
este.item.preço.toString()),
RatingBox(), ], )))
]),
),
), );
}
}
void _setRatingAsOne()
{ setState(()
{ _rating = 1; });
void _setRatingAsTwo()
{ setState(()
{ _rating = 2; });
void _setRatingAsThree()
{ setState(() {
77
Machine Translated by Google
Vibração
_classificação =
3; });
}
return
Row( mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end, mainAxisSize:
MainAxisSize.max, filhos:
(Ícones.estrela, tamanho:
_tamanho,
)
:
Icon( Icons.star_border, tamanho:
_size, )), cor:
Colors.red[500], onPressed:
_setRatingAsOne, iconSize: _size, ), ),
Container( preenchimento:
EdgeInsets.all(0),
filho: IconButton(
(Ícones.estrela, tamanho:
_tamanho,
)
: Ícone
( Icons.star_border,
tamanho: _size, )),
cor:
Colors.red [500], onPressed:
_setRatingAsTwo, iconSize: _size, ), ),
Container ( preenchimento:
EdgeInsets.all
(0), filho: IconButton (
(Ícones.estrela, tamanho:
_tamanho,
)
78
Machine Translated by Google
Vibração
:
Icon( Icons.star_border,
size: _size, )),
color: Colors.red[500],
onPressed: _setRatingAsThree,
iconSize: _size, ), ), ], );
}
}
Expanded( child:
Container( padding: EdgeInsets.all(5),
child:
Column( mainAxisAlignment :
MainAxisAlignment.spaceEvenly, filhos: <Widget>[
Text(este.item.nome,
estilo: TextStyle(fontWeight:
Intensidade da fonte: Negrito)),
Text(this.item.description),
Text("Preço: " + this.item.price.toString()), RatingBox(), ], )))
]),
));
}
}
79
Machine Translated by Google
Vibração
Execute o aplicativo e clique em qualquer item do produto. Ele mostrará a página de detalhes relevantes. Podemos
ir para a página inicial clicando no botão Voltar. A página da lista de produtos e a página de detalhes do produto
do aplicativo são mostradas a seguir:
80
Machine Translated by Google
Vibração
81
Machine Translated by Google
A animação é um procedimento complexo em qualquer aplicativo móvel. Apesar de sua complexidade, a Animação eleva a
experiência do usuário a um novo nível e proporciona uma rica interação do usuário. Devido à sua riqueza, a animação torna-se
parte integrante dos aplicativos móveis modernos. A estrutura Flutter reconhece a importância da animação e fornece uma
Introdução
Animação é um processo de mostrar uma série de imagens/imagem em uma ordem específica e com uma duração específica
para dar uma ilusão de movimento. Os aspectos mais importantes da animação são os seguintes:
• A animação tem dois valores distintos: valor inicial e valor final. A animação começa no valor inicial e passa por uma série de
valores intermediários e finalmente termina nos valores finais . Por exemplo, para animar o desaparecimento de um widget,
o valor inicial será a opacidade total e o valor final será a opacidade zero.
• Os valores intermediários podem ser de natureza linear ou não linear (curva) e podem ser configurados. Entenda que a
animação funciona conforme está configurada. Cada configuração fornece uma sensação diferente à animação. Por
exemplo, o desbotamento de um widget será de natureza linear, enquanto o salto de uma bola será de natureza não linear.
• A capacidade de controlar o processo de animação, como iniciar a animação, parar a animação, repetir a animação para definir
um número de vezes, reverter o processo de animação, etc.,
• No Flutter, o sistema de animação não faz nenhuma animação real. Em vez disso, fornece apenas os valores necessários
em cada quadro para renderizar as imagens.
Animação
Gera valores interpolados entre dois números durante um determinado período. As aulas de animação mais comuns são:
82
Machine Translated by Google
Vibração
• AnimationController - Objeto de animação especial para controlar a própria animação. Ele gera novos valores sempre
que a aplicação está pronta para um novo quadro. Ele suporta animação linear e o valor começa de 0,0 a 1,0.
Aqui, o controlador controla a animação e a opção de duração controla a duração do processo de animação. vsync
é uma opção especial utilizada para otimizar o recurso utilizado na animação.
Animação Curva
Semelhante ao AnimationController, mas oferece suporte a animação não linear. CurvedAnimation pode ser usado junto com
o objeto Animation conforme abaixo:
Interpolação<T>
Derivado de Animatable<T> e usado para gerar números entre quaisquer dois números diferentes de 0 e 1. Ele pode ser
usado junto com o objeto Animation usando o método animate e passando o objeto Animation real.
Tween também pode ser usado junto com CurvedAnimation conforme abaixo:
Aqui, controller é o controlador de animação real. curve fornece o tipo de não linearidade e o customTween fornece intervalo
personalizado de 0 a 255.
83
Machine Translated by Google
Vibração
});
• Widgets integrados, AnimatedWidget e AnimatedBuilder podem ser usados para pular esse processo. Ambos os widgets
aceitam o objeto Animation e obtêm os valores atuais necessários para a animação.
• Obtenha os valores da animação durante o processo de construção do widget e depois aplique-os para largura, altura
ou qualquer propriedade relevante em vez do valor original.
Aplicativo de trabalho
Vamos escrever um aplicativo simples baseado em animação para entender o conceito de animação no framework Flutter.
• Copie a pasta de ativos de product_nav_app para product_animation_app e adicione ativos dentro do arquivo
pubspec.yaml
vibração:
ativos:
- assets/appimages/floppy.png
- ativos/appimages/iphone.png
- ativos/appimages/laptop.png
- assets/appimages/pendrive.png
- ativos/appimages/pixel.png
- ativos/appimages/tablet.png
importar 'pacote:flutter/material.dart';
84
Machine Translated by Google
Vibração
• Crie o widget _MyAppState e implemente initState e descarte além do método de construção padrão.
Animação<duplo> animação;
Controlador AnimationController;
@override
void initState() {
super.initState(); controlador
= AnimationController(duração: const Duração(segundos: 10), vsync: this);
demonstração de layout
de produto', animação: animação,)
);
}
@override
void dispor()
{ controller.dispose();
super.dispose();
}
}
Aqui,
• No método initState, criamos um objeto controlador de animação (controller), um objeto de animação (animação) e
iniciamos a animação usando controller.forward.
• No método build, envie animação para o widget MyHomePage por meio do construtor. Agora, o widget MyHomePage
pode usar o objeto de animação para animar seu conteúdo.
85
Machine Translated by Google
Vibração
: super(chave: chave);
Container( padding:
EdgeInsets.all(5), child:
])));
}
}
• Crie um novo widget, MyAnimatedWidget, para fazer uma animação simples de fade usando opacidade.
);
}
• Aqui, usamos AniatedBuilder para fazer nossa animação. AnimatedBuilder é um widget que constrói seu
conteúdo enquanto faz a animação ao mesmo tempo. Aceita um objeto de animação para obter o valor
atual da animação. Usamos animação
86
Machine Translated by Google
Vibração
value, Animation.value para definir a opacidade do widget filho. Na verdade, o widget irá animar o widget
filho usando o conceito de opacidade.
• Por fim, crie o widget MyHomePage e use o objeto de animação para animar qualquer conteúdo.
@override
Widget build (contexto BuildContext) { return
Scaffold( appBar:
AppBar(title: Text("Listagem de produtos")), body:
ListView( ShrinkWrap:
true, padding: const
EdgeInsets.fromLTRB(2.0, 10.0, 2.0, 10.0) , filhos: <Widget>[ FadeTransition(child:
ProductBox( nome:
"iPhone", descrição: "iPhone é o telefone
estilista de todos os
tempos", preço: 1000, imagem: "iphone.png"), opacidade:
animação),
MyAnimatedWidget( filho:
ProductBox (nome: "Pixel",
descrição: "Pixel é o telefone com mais recursos
de todos os
tempos", preço: 800, imagem: "pixel.png"),
animação: animação),
ProductBox( nome:
"Laptop", descrição: "Laptop é a ferramenta de desenvolvimento mais produtiva",
preço: 2000,
imagem: "laptop.png"),
ProductBox( nome:
"Tablet", descrição: "Tablet é o dispositivo mais útil de todos os tempos
reunião",
preço: 1500,
imagem: "tablet.png"),
ProductBox( nome:
"Pendrive", descrição: "Pendrive é um meio de armazenamento útil",
preço: 100,
imagem: "pendrive.png"),
87
Machine Translated by Google
Vibração
));
}
}
Aqui, usamos FadeAnimation e MyAnimationWidget para animar os dois primeiros itens da lista. FadeAnimation
é uma classe de animação integrada, que usamos para animar seu filho usando o conceito de opacidade.
importar 'pacote:flutter/material.dart';
Animação<duplo> animação;
Controlador AnimationController;
@override
void initState() {
super.initState();
controlador = AnimationController(duração: const Duração(segundos: 10), vsync: this);
animação =
Tween<double>(início: 0,0, fim: 1,0).animate(controlador); controlador.forward();
de demonstração de
layout de produto', animação: animação,)
);
}
@override
void dispor()
{ controller.dispose();
super.dispose();
}
}
88
Machine Translated by Google
Vibração
@override
Widget build (contexto BuildContext) { return
Scaffold( appBar:
AppBar(title: Text("Listagem de produtos")), body:
ListView( ShrinkWrap:
true, padding: const
EdgeInsets.fromLTRB(2.0, 10.0, 2.0, 10.0) , filhos: <Widget>[ FadeTransition(child:
ProductBox( nome:
"iPhone", descrição: "iPhone é o telefone
estilista de todos os
tempos", preço: 1000, imagem: "iphone.png"), opacidade:
animação),
MyAnimatedWidget( filho:
ProductBox (nome: "Pixel",
descrição: "Pixel é o telefone com mais recursos
de todos os
tempos", preço: 800, imagem: "pixel.png"),
animação: animação),
ProductBox( nome:
"Laptop", descrição: "Laptop é a ferramenta de desenvolvimento mais produtiva",
preço: 2000,
imagem: "laptop.png"),
ProductBox( nome:
"Tablet", descrição: "Tablet é o dispositivo mais útil de todos os tempos
reunião",
preço: 1500,
imagem: "tablet.png"),
ProductBox( nome:
"Pendrive", descrição: "Pendrive é um meio de armazenamento útil",
preço: 100,
imagem: "pendrive.png"),
ProductBox(
name: "Unidade de disquete",
description: "A unidade de disquete é um armazenamento de resgate útil
médio",
preço: 20,
imagem: "floppy.png"),
], ));
}
}
89
Machine Translated by Google
Vibração
Container( padding:
EdgeInsets.all(5), child:
])));
}
}
);
}
90
Machine Translated by Google
Vibração
91
Machine Translated by Google
Vibração
92
Machine Translated by Google
Vibração
11. Flutter – Escrevendo código específico do Android
Flutter fornece uma estrutura geral para acessar recursos específicos da plataforma. Isso permite que o desenvolvedor
estenda a funcionalidade da estrutura Flutter usando código específico da plataforma.
Funcionalidades específicas da plataforma, como câmera, nível de bateria, navegador, etc., podem ser acessadas
facilmente por meio da estrutura.
A ideia geral de acessar o código específico da plataforma é através de um protocolo de mensagens simples. O código
Flutter, o Cliente e o código da plataforma e o Host são vinculados a um canal de mensagem comum. O cliente envia
mensagem ao Host através do Canal de Mensagens. O Host escuta no Canal de Mensagens, recebe a mensagem e
faz as funcionalidades necessárias e por fim, retorna o resultado ao Cliente através do Canal de Mensagens.
O protocolo de mensagens usa um codec de mensagem padrão (classe StandardMessageCodec) que suporta
serialização binária de valores semelhantes a JSON, como números, strings, booleanos, etc.. A serialização e
desserialização funcionam de forma transparente entre o cliente e o
hospedar.
Vamos escrever um aplicativo simples para abrir um navegador usando Android SDK e entender como invocar o SDK
a partir de um aplicativo flutter.
importar 'pacote:flutter/material.dart';
93
Machine Translated by Google
Vibração
);
}
}
@override
Widget build (contexto BuildContext) { return
Scaffold( appBar:
AppBar( title:
Text(this.title), ), body: Center( child:
RaisedButton( child:
Text('Open Browser'),
onPressed: null, ) , ), );
}
}
• Aqui, criamos um novo botão para abrir o navegador e definimos seu método onPressed como nulo.
}
}
94
Machine Translated by Google
Vibração
Aqui, usamos platform.invokeMethod para invocar o openBrowser (explicado nas próximas etapas). openBrowser
tem um argumento url para abrir uma url específica.
onPressed: _openBrowser,
private void openBrowser (MethodCall call, Result result, String url) { Activity Activity = this; if (activity
== null)
atividade.startActivity(intenção);
resultado.sucesso((Objeto) verdadeiro);
}
• Escreva o código específico do Android para definir o tratamento de mensagens no método onCreate.
if (call.method.equals("openBrowser")) {
95
Machine Translated by Google
Vibração
}
});
Aqui, criamos um canal de mensagem usando a classe MethodChannel e usamos a classe MethodCallHandler
para lidar com a mensagem. onMethodCall é o método real responsável por chamar o código específico da
plataforma correta verificando a mensagem. O método onMethodCall extrai o URL da mensagem e então
invoca o openBrowser somente quando a chamada do método é openBrowser. Caso contrário, ele retornará o
método notImplemented.
principal.dart
MainActivity.java
pacote com.tutorialspoint.flutterapp.flutter_browser_app;
@Override
protegido void onCreate(Bundle saveInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
if (call.method.equals("openBrowser"))
{ openBrowser(chamada, resultado, url); }
else
{ resultado.notImplemented();
}
96
Machine Translated by Google
Vibração
});
}
atividade.startActivity(intenção);
resultado.sucesso((Objeto) verdadeiro);
}
}
principal.dart
importar 'pacote:flutter/material.dart';
}
}
97
Machine Translated by Google
Vibração
@override
Widget build (contexto BuildContext) { return
Scaffold( appBar:
AppBar( title:
Text(this.title), ), body:
Center( child:
RaisedButton( child:
Text('Open Browser'), onPressed:
_openBrowser, ) , ), );
}
}
Execute o aplicativo e clique no botão Abrir navegador e você verá que o navegador foi iniciado. O aplicativo
Navegador - página inicial é mostrado na captura de tela aqui:
98
Machine Translated by Google
Vibração
99
Machine Translated by Google
Vibração
12. Flutter – Escrevendo código específico para iOS
O acesso ao código específico do iOS é semelhante ao da plataforma Android, exceto que usa linguagens
específicas do iOS - Objective-C ou Swift e iOS SDK. Caso contrário, o conceito é o mesmo da plataforma
Android.
Vamos escrever o mesmo aplicativo do capítulo anterior também para a plataforma iOS.
• Vamos criar um novo aplicativo no Android Studio (macOS), flutter_browser_ios_app
#include "AppDelegate.h"
#include "GeneratedPluginRegistrant.h"
@implementação AppDelegate
- (BOOL)aplicativo:(UIApplication *)aplicativo
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//
[GeneratedPluginRegistrant RegisterWithRegistry:self];
// Substituir ponto para personalização após inicialização do aplicativo.
return [super aplicativo: aplicativo
didFinishLaunchingWithOptions:launchOptions];
}
@fim
• Adicionamos um método openBrowser para abrir o navegador com o URL especificado. Isto
aceita um único argumento, url.
- (void)openBrowser:(NSString *)urlString {
NSURL *url = [NSURL URLWithString:urlString];
UIApplication *application = [UIApplication sharedApplication];
[aplicativo openURL:url];
}
100
Machine Translated by Google
Vibração
Controlador FlutterViewController* =
(FlutterViewController*)self.window.rootViewController;
métodoChannelWithName:@"flutterapp.tutorialspoint.com/browser"
binárioMessenger:controlador];
{ resultado(FlutterMethodNotImplemented);
}
}];
#include "AppDelegate.h"
#include "GeneratedPluginRegistrant.h"
@implementação AppDelegate
- (BOOL)aplicativo:(UIApplication *)aplicativo
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
métodoChannelWithName:@"flutterapp.tutorialspoint.com/browser"
binárioMessenger:controlador];
101
Machine Translated by Google
Vibração
{ resultado(FlutterMethodNotImplemented);
}
}];
- (void)openBrowser:(NSString *)urlString {
NSURL *url = [NSURL URLWithString:urlString];
UIApplication *application = [UIApplication sharedApplication];
[aplicativo openURL:url];
}
@fim
• Agora, execute o aplicativo. Funciona de forma semelhante à versão Android, mas o navegador Safari
será aberto em vez do Chrome.
102
Machine Translated by Google
A maneira do Dart organizar e compartilhar um conjunto de funcionalidades é por meio do Package. O pacote Dart consiste
simplesmente em bibliotecas ou módulos compartilháveis. Em geral, o pacote Dart é igual ao aplicativo Dart, exceto que o
pacote Dart não possui ponto de entrada do aplicativo, principal.
• Outro arquivo de código privado pode ser exportado para o arquivo de código principal
(my_demo_package.dart), se necessário, conforme mostrado abaixo:
exportar src/meu_código_privado.dart
• lib/* : qualquer número de arquivos de código Dart organizados em qualquer estrutura de pastas personalizada.
O código pode ser acessado como,
Todos os arquivos de código Dart no pacote são simplesmente classes Dart e não há nenhum requisito especial para um
código Dart incluí-lo em um pacote.
Tipos de pacotes
Como os pacotes Dart são basicamente uma pequena coleção de funcionalidades semelhantes, eles podem ser categorizados
com base em sua funcionalidade.
Pacote Dardo
Código Dart genérico, que pode ser usado tanto em ambiente web quanto móvel. Por exemplo, english_words é um desses
pacotes que contém cerca de 5.000 palavras e possui funções utilitárias básicas como substantivos (listar substantivos em
inglês), sílabas (especificar o número de sílabas em uma palavra.
Pacote Flutter
Código Dart genérico, que depende do framework Flutter e pode ser usado apenas em ambiente móvel. Por exemplo, fluro é
um roteador personalizado para flutter. Depende da vibração
estrutura.
103
Machine Translated by Google
Vibração
Plug-in Flutter
Código Dart genérico, que depende da estrutura Flutter, bem como do código da plataforma subjacente (Android SDK ou iOS SDK). Por
exemplo, câmera é um plugin para interagir com a câmera do dispositivo. Depende da estrutura Flutter, bem como da estrutura
subjacente para obter acesso à câmera.
dependências:
palavras_inglês: ^3.1.5
• O número da versão mais recente pode ser encontrado verificando o servidor online.
• Durante o desenvolvimento no Android Studio, o Android Studio detecta qualquer alteração no pubspec.yaml e exibe
um alerta de pacote do Android Studio para o desenvolvedor, conforme mostrado abaixo:
• Os pacotes Dart podem ser instalados ou atualizados no Android Studio usando as opções do menu.
importar 'pacote:english_words/english_words.dart';
substantivos.take(50).forEach(print);
Como já aprendemos como acessar o código da plataforma nos capítulos anteriores, vamos desenvolver um plugin simples,
my_browser, para entender o processo de desenvolvimento do plugin. O
104
Machine Translated by Google
Vibração
A funcionalidade do plugin my_browser é permitir que o aplicativo abra um determinado site no navegador
específico da plataforma.
• Clique em Arquivo -> Novo projeto Flutter e selecione a opção Flutter Plugin.
• Você pode ver uma janela de seleção do plugin Flutter conforme mostrado aqui:
105
Machine Translated by Google
Vibração
• Insira o domínio da empresa, flutterplugins.tutorialspoint.com na janela mostrada abaixo e clique em Concluir. Ele irá
gerar um código de inicialização para desenvolver nosso novo plugin.
106
Machine Translated by Google
Vibração
• Aqui, temos que importar a biblioteca necessária para abrir um navegador do Android.
@Override
public void onMethodCall(MethodCall call, Result result) {
107
Machine Translated by Google
Vibração
if (call.method.equals("getPlatformVersion")) { result.success("Android
" + android.os.Build.VERSION.RELEASE); } else if (call.method.equals("openBrowser")) {
{ resultado.notImplemented();
}
}
atividade.startActivity(intenção);
resultado.sucesso((Objeto) verdadeiro);
}
meu_navegador.dart
importar 'pacote:flutter/services.dart';
108
Machine Translated by Google
Vibração
}
}
MeuBrowserPlugin.java
pacote com.tutorialspoint.flutterplugins.my_browser;
MyBrowserPlugin(registrador); canal.setMethodCallHandler(instância);
@Override
public void onMethodCall(MethodCall call, Result result) {
String url = call.argument("url");
if (call.method.equals("getPlatformVersion")) { result.success("Android
" + android.os.Build.VERSION.RELEASE); } else if (call.method.equals("openBrowser"))
{
openBrowser(chamada, resultado, url); }
else
{ resultado.notImplemented();
}
}
109
Machine Translated by Google
Vibração
atividade.startActivity(intenção);
resultado.sucesso((Objeto) verdadeiro);
}
}
dependências:
vibração:
SDK: vibração
meu_navegador:
caminho: ../meu_navegador
• O Android Studio alertará que pubspec.yaml foi atualizado conforme mostrado no alerta de pacote do Android
Studio fornecido abaixo:
• Clique na opção Obter dependências. O Android Studio obterá o pacote da Internet e o configurará
adequadamente para o aplicativo.
importar 'pacote:meu_browser/meu_browser.dart';
ThemeData(primárioSwatch:
110
Machine Translated by Google
Vibração
}
}
@override
Widget build (contexto BuildContext) { return
Scaffold( appBar:
AppBar( title:
Text(this.title), ), body:
Center( child:
RaisedButton( child:
Text('Open Browser'), onPressed: ()
= > MeuBrowser().openBrowser("https://flutter.dev"), ), ), );
}
}
111
Machine Translated by Google
Vibração
• Execute o aplicativo e clique no botão Abrir navegador e veja se o navegador é iniciado. Você pode ver um aplicativo de
navegador - página inicial conforme mostrado na captura de tela abaixo:
112
Machine Translated by Google
Vibração
• Você pode ver um aplicativo de navegador - tela do navegador conforme mostrado na captura de tela mostrada
abaixo:
113
Machine Translated by Google
Vibração
14. Flutter – Acessando API REST
Flutter fornece pacote http para consumir recursos HTTP. http é uma biblioteca baseada no futuro e usa recursos de espera
e assíncronos. Ele fornece muitos métodos de alto nível e simplifica o desenvolvimento de aplicativos móveis baseados em
REST.
Conceitos Básicos
O pacote http fornece uma classe de alto nível e http para fazer solicitações da web.
• A classe http fornece funcionalidade para executar todos os tipos de solicitações HTTP.
• Os métodos http aceitam uma URL e informações adicionais através do Dart Map (dados de postagem, cabeçalhos
adicionais, etc.). Ele solicita o servidor e coleta a resposta de volta no padrão assíncrono/aguardado. Por exemplo,
o código abaixo lê os dados do URL especificado e os imprime no console.
print(aguarde http.read('https://flutter.dev/'));
• read - Solicita a url especificada através do método GET e retorna a resposta como Future<String>
• get - Solicita a url especificada através do método GET e retorna a resposta como Future<Response>. Response é
uma classe que contém as informações da resposta.
• post - Solicite a url especificada através do método POST postando os dados fornecidos e retorne a resposta como
Future<Response>
http também fornece uma classe de cliente HTTP mais padrão, client. cliente suporta conexão persistente. Será útil quando
houver muitas solicitações a serem feitas a um servidor específico. Ele precisa ser fechado corretamente usando o método
close. Caso contrário, é semelhante à classe http. O código de exemplo é o seguinte:
114
Machine Translated by Google
Vibração
Acessando ProductserviceAPI
Vamos criar um aplicativo simples para obter dados de produtos de um servidor web e depois mostrar os produtos
usando ListView.
vibração:
ativos:
- assets/appimages/floppy.png - assets/
appimages/iphone.png - assets/
appimages/laptop.png - assets/
appimages/pendrive.png - assets/
appimages/pixel.png - assets/
appimages/tablet.png
dependências:
http: ^0.12.0+2
• Aqui, usaremos a versão mais recente do pacote http. O Android Studio enviará um alerta de pacote
informando que pubspec.yaml foi atualizado.
• Clique na opção Obter dependências. O Android Studio obterá o pacote da Internet e o configurará
adequadamente para o aplicativo.
• Crie um novo arquivo JSON, products.json com informações do produto conforme mostrado abaixo:
[
{
"name": "iPhone",
"description": "iPhone é o telefone estilista de todos os tempos",
"price": 1000,
"image": "iphone.png"
},
{
"name": "Pixel",
"description": "Pixel é o telefone com mais recursos de todos os tempos",
"price": 800,
"image": "pixel.png"
115
Machine Translated by Google
Vibração
},
{
"name": "Laptop",
"description": "Laptop é a ferramenta de desenvolvimento mais produtiva", "price": 2000,
"image": "laptop.png"
},
{
"name": "Tablet",
"description": "Tablet é o dispositivo mais útil para reuniões", "price": 1500, "image": "tablet.png"
},
{
"name": "Pendrive",
"description": "Pendrive é um meio de armazenamento útil", "price": 100,
"image":
"pendrive.png"
},
{
"name": "Unidade de disquete",
"description": "A unidade de disquete é um meio de armazenamento de resgate útil", "price":
20, "image":
"floppy.png"
}
]
• Execute qualquer servidor web com JSONWebServer como diretório raiz e obtenha seu caminho web.
Por exemplo, http://192.168.184.1:8000/products.json. Podemos usar qualquer servidor web como apache, nginx
etc.,
• A maneira mais fácil é instalar um aplicativo de servidor http baseado em nó. Siga os passos dados
abaixo para instalar e executar o aplicativo de servidor http.
cd /caminho/para/JSONWebServer
116
Machine Translated by Google
Vibração
http://127.0.0.1:8000
Pressione CTRL-C para parar o servidor
• Crie um novo arquivo, Product.dart na pasta lib e mova a classe Product para ele.
• Escreva um construtor de fábrica na classe Product, Product.fromMap, para converter o mapa de dados
mapeado no objeto Product. Normalmente, o arquivo JSON será convertido em objeto Dart Map e,
em seguida, convertido em objeto relevante (Produto)
Produto(dados['nome'],
dados['descrição'],
dados['preço'],
dados['imagem'], );
}
classe Produto
{ final String nome;
descrição final da String; preço
interno final; imagem
final da String;
}
}
• Escreva dois métodos - parseProducts e fetchProducts - na classe principal para buscar e carregar as
informações do produto do servidor web no objeto List<Product>.
if (response.statusCode == 200) {
return parseProducts(response.body); } else
{ throw
Exception('Não foi possível buscar produtos da API REST');
117
Machine Translated by Google
Vibração
}
}
• Future é usado para carregar lentamente as informações do produto. O carregamento lento é um conceito para adiar
a execução do código até que seja necessário.
• json.decode é usado para decodificar os dados JSON no objeto Dart Map. Depois que os dados JSON forem
decodificados, eles serão convertidos em List<Product> usando fromMap da classe Product.
• Na classe MyApp, adicione uma nova variável de membro, produtos do tipo Future<Product> e inclua-a no construtor.
...
• Na classe MyHomePage, adicione novos produtos variáveis de membro do tipo Future<Product> e inclua-os no
construtor. Além disso, remova a variável items e seu método relevante, chamada do método getProducts.
Colocando a variável produtos no construtor. Permitirá buscar os produtos na Internet apenas uma vez, quando o
aplicativo for iniciado pela primeira vez.
home: MinhaPáginaHome(
título: 'Página inicial de demonstração de navegação de produto',
produtos: produtos),
• Crie um novo widget, ProductBoxList para construir a lista de produtos na página inicial.
118
Machine Translated by Google
Vibração
ProductBoxList({Chave-chave, this.items});
@override
Widget build (contexto BuildContext) { return
ListView.builder (
itemCount: items.length, itemBuilder:
(contexto, índice) { return GestureDetector( filho:
ProductBox(item: itens[índice]),
onTap: () { Navigator.push( context, MaterialPageRoute(
}
}
Observe que usamos o mesmo conceito usado no aplicativo Navigation para listar o produto, exceto que ele foi projetado
como um widget separado, passando produtos (objeto) do tipo List<Product>.
• Por fim, modifique o método de construção do widget MyHomePage para obter as informações do
produto usando a opção Future em vez da chamada de método normal.
retornar snapshot.hasData?
ProductBoxList( items:
snapshot.data) // retorna o widget ListView
: Centro(filho: CircularProgressIndicator());
}, ), ));
}
• Observe aqui que usamos o widget FutureBuilder para renderizar o widget. Construtor do Futuro
tentará buscar os dados de sua propriedade futura (do tipo Future<List<Product>>).
Se a propriedade futura retornar dados, ela renderizará o widget usando ProductBoxList, caso contrário,
gerará um erro.
119
Machine Translated by Google
Vibração
importar 'pacote:flutter/material.dart';
importar 'Produto.dart';
if (response.statusCode == 200) {
return parseProducts(response.body); } else
{ throw
Exception('Não foi possível buscar produtos da API REST');
}
}
ThemeData( primárioSwatch:
Colors.blue, ), home:
MyHomePage( título: 'Página inicial de demonstração de navegação de
produto',
produtos: produtos), );
}
}
120
Machine Translated by Google
Vibração
@sobrepor
Construção de widget (contexto BuildContext)
{ return Scaffold( appBar:
AppBar(title: Text("Navegação do produto")), body: Center( child:
if (instantâneo.hasError) imprimir(instantâneo.error);
retornar snapshot.hasData?
ProductBoxList( items:
snapshot.data) // retorna o widget ListView
: Centro(filho: CircularProgressIndicator());
}, ), ));
}
}
ProductBoxList({Chave-chave, this.items});
@override
Widget build (contexto BuildContext) { return
ListView.builder (
itemCount: items.length,
itemBuilder: (contexto, índice) { return
GestureDetector( filho:
ProductBox(item: itens[índice]), onTap: ()
{ Navigator.push( context,
MaterialPageRoute(
construtor: (contexto) => ProductPage(item: itens[índice]), ), ); }, ); }, );
}
}
@sobrepor
Construção de widget (contexto BuildContext)
{ return Scaffold (
121
Machine Translated by Google
Vibração
appBar: AppBar
(título: Texto (este.item.nome),),
corpo: Centro
(filho: Container
(preenchimento: EdgeInsets.all (0),
filho: Coluna
(mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start, filhos:
<Widget>[Image.asset("assets/
appimages/" + this.item.image), Expanded( filho:
Container( preenchimento:
EdgeInsets.all(5), filho:
Column( mainAxisAlignment:
MainAxisAlignment.spaceEvenly,
filhos: <Widget>[
Text(este.item.nome,
estilo: TextStyle(fontWeight:
Intensidade da fonte: Negrito)),
Text(this.item.description),
Text("Preço: " + this.item.price.toString()), RatingBox(), ], )))
]),
), ), );
}
}
void _setRatingAsOne()
{ setState(()
{ _rating = 1; });
void _setRatingAsTwo()
{ setState(()
{ _rating = 2; });
void _setRatingAsThree()
{ setState(() {
122
Machine Translated by Google
Vibração
_classificação =
3; });
}
return
Row( mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end, mainAxisSize:
MainAxisSize.max, filhos:
(Ícones.estrela, tamanho:
_tamanho,
)
:
Icon( Icons.star_border, tamanho:
_size, )), cor:
Colors.red[500], onPressed:
_setRatingAsOne, iconSize: _size, ), ),
Container( preenchimento:
EdgeInsets.all(0),
filho: IconButton(
(Ícones.estrela, tamanho:
_tamanho,
)
: Ícone
( Icons.star_border,
tamanho: _size, )),
cor:
Colors.red [500], onPressed:
_setRatingAsTwo, iconSize: _size, ), ),
Container ( preenchimento:
EdgeInsets.all
(0), filho: IconButton (
(Ícones.estrela, tamanho:
_tamanho,
)
123
Machine Translated by Google
Vibração
:
Icon( Icons.star_border,
size: _size, )),
color: Colors.red[500],
onPressed: _setRatingAsThree,
iconSize: _size, ), ), ], );
}
}
Expanded( child:
Container( padding: EdgeInsets.all(5),
child:
Column( mainAxisAlignment :
MainAxisAlignment.spaceEvenly, filhos: <Widget>[
Text(este.item.nome,
estilo: TextStyle(fontWeight:
Intensidade da fonte: Negrito)),
Text(this.item.description),
Text("Preço: " + this.item.price.toString()), RatingBox(), ], )))
]),
));
}
}
Por fim, execute o aplicativo para ver o resultado. Será igual ao nosso exemplo de navegação , exceto que
os dados são da Internet, em vez de dados estáticos locais inseridos durante a codificação do aplicativo.
124
Machine Translated by Google
Vibração
15. Flutter – Conceitos de banco de dados
Flutter fornece muitos pacotes avançados para trabalhar com bancos de dados. Os pacotes mais importantes são:
• firebase_database – Usado para acessar e manipular banco de dados NoSQL hospedado na nuvem
do Google.
SQLite
O banco de dados SQLite é o mecanismo de banco de dados incorporado baseado em SQL padrão e de fato. É um
mecanismo de banco de dados pequeno e testado pelo tempo. O pacote sqflite fornece muitas funcionalidades para
trabalhar de forma eficiente com o banco de dados SQLite. Ele fornece métodos padrão para manipular o mecanismo de
banco de dados SQLite. A funcionalidade principal fornecida pelo pacote sqflite é a seguinte:
• Métodos de consulta avançados (método de consulta) para reduzir o código necessário para consultar e
obter informações do banco de dados SQLite.
Vamos criar um aplicativo de produto para armazenar e buscar informações de produto de um mecanismo de banco de
dados SQLite padrão usando o pacote sqflite e entender o conceito por trás do banco de dados SQLite e do pacote sqflite.
vibração:
ativos:
- assets/appimages/floppy.png
- ativos/appimages/iphone.png
- ativos/appimages/laptop.png
- assets/appimages/pendrive.png
- ativos/appimages/pixel.png
- ativos/appimages/tablet.png
dependências:
sqflite: qualquer
125
Machine Translated by Google
Vibração
dependências:
path_provider: qualquer
• Aqui, o pacote path_provider é usado para obter o caminho da pasta temporária do sistema e o caminho do
aplicativo. Use o número da versão mais recente do sqflite no lugar de qualquer.
• Clique na opção Obter dependências. O Android Studio obterá o pacote da Internet e o configurará
adequadamente para o aplicativo.
• No banco de dados, precisamos de chave primária, id como campo adicional junto com propriedades do
produto como nome, preço, etc., portanto, adicione a propriedade id na classe Produto. Além disso, adicione
um novo método, toMap, para converter o objeto produto em objeto Map. fromMap e toMap são usados
para serializar e desserializar o objeto Product e são usados em métodos de manipulação de banco de
dados.
• Crie um novo arquivo, Database.dart na pasta lib para escrever funcionalidades relacionadas ao SQLite .
126
Machine Translated by Google
Vibração
importar 'Produto.dart';
• path é usado para acessar a função principal do utilitário Dart relacionada aos caminhos de arquivos.
classe SQLiteDbProvider
{ SQLiteDbProvider._();
• O objeto SQLiteDBProvoider e seu método podem ser acessados através do banco de dados estático
variável.
SQLiteDBProvoider.db.<emthod>
• Crie um método para obter banco de dados (opção Future) do tipo Future<Database>.
Crie a tabela de produtos e carregue os dados iniciais durante a criação do próprio banco de dados.
initDB() assíncrono {
Documentos do diretórioDiretório = aguardar
getApplicationDocumentsDirectory(); String caminho
= join(documentsDirectory.path, "ProductDB.db"); return aguarda openDatabase(caminho,
versão: 1,
127
Machine Translated by Google
Vibração
aguarde db.execute (
"INSERT INTO Produto ('id', 'nome', 'descrição', 'preço',
'imagem') valores (?, ?, ?, ?, ?)",
[1, "iPhone", "iPhone é o telefone estilista de todos os tempos", 1000,
"iphone.png"]);
aguarde db.execute (
"INSERT INTO Produto ('id', 'nome', 'descrição', 'preço',
'imagem') valores (?, ?, ?, ?, ?)",
[2, "Pixel", "Pixel é o telefone com mais recursos de todos os tempos", 800,
"pixel.png"]);
aguarde db.execute (
"INSERT INTO Produto ('id', 'nome', 'descrição', 'preço',
'imagem') valores (?, ?, ?, ?, ?)",
[3, "Laptop", "Laptop é a ferramenta de desenvolvimento mais produtiva",
2000, "laptop.png"]);
aguarde db.execute (
"INSERT INTO Produto ('id', 'nome', 'descrição', 'preço',
'imagem') valores (?, ?, ?, ?, ?)",
[4, "Tablet", "Laptop é a ferramenta de desenvolvimento mais produtiva",
1500, "tablet.png"]);
aguarde db.execute (
"INSERT INTO Produto ('id', 'nome', 'descrição', 'preço',
'imagem') valores (?, ?, ?, ?, ?)",
[5, "Pendrive", "Pendrive é um meio de armazenamento útil", 100, "pendrive.png"]);
aguarde db.execute (
"INSERT INTO Produto ('id', 'nome', 'descrição', 'preço',
'imagem') valores (?, ?, ?, ?, ?)",
[6, "Unidade de disquete", "A unidade de disquete é um meio de armazenamento de
resgate útil", 20, "floppy.png"]);
});
}
• join - Usado para criar um caminho específico do sistema. Nós o usamos para criar banco de dados
caminho.
128
Machine Translated by Google
Vibração
• onCreate - Usado para escrever código enquanto um banco de dados é criado pela primeira vez
• db.execute - Usado para executar consultas SQL. Ele aceita uma consulta. Se a consulta tiver
espaço reservado (?), então aceita valores como lista no segundo argumento.
devolver produtos;
}
• Método de consulta utilizado para buscar todas as informações do produto. query fornece um atalho para consultar
informações de uma tabela sem escrever a consulta inteira. query irá gerar a consulta adequada usando
nossas entradas como colunas, orderBy, etc.,
• Usei o método fromMap do produto para obter detalhes do produto repetindo os resultados
objeto, que contém todas as linhas da tabela.
• Crie três métodos - método de inserção, atualização e exclusão para inserir, atualizar e excluir produto do banco
de dados
129
Machine Translated by Google
Vibração
var id = maxIdResult.first["last_inserted_id"];
resultado de retorno;
}
resultado de retorno;
}
importar 'Produto.dart';
classe SQLiteDbProvider
{ SQLiteDbProvider._();
initDB() assíncrono {
130
Machine Translated by Google
Vibração
aguarde db.execute (
"INSERT INTO Produto ('id', 'nome', 'descrição', 'preço',
'imagem') valores (?, ?, ?, ?, ?)",
[1, "iPhone", "iPhone é o telefone estilista de todos os tempos", 1000,
"iphone.png"]);
aguarde db.execute (
"INSERT INTO Produto ('id', 'nome', 'descrição', 'preço',
'imagem') valores (?, ?, ?, ?, ?)",
[2, "Pixel", "Pixel é o telefone com mais recursos de todos os tempos", 800,
"pixel.png"]);
aguarde db.execute (
"INSERT INTO Produto ('id', 'nome', 'descrição', 'preço',
'imagem') valores (?, ?, ?, ?, ?)",
[3, "Laptop", "Laptop é a ferramenta de desenvolvimento mais produtiva",
2000, "laptop.png"]);
aguarde db.execute (
"INSERT INTO Produto ('id', 'nome', 'descrição', 'preço',
'imagem') valores (?, ?, ?, ?, ?)",
[4, "Tablet", "Laptop é a ferramenta de desenvolvimento mais produtiva",
1500, "tablet.png"]);
aguarde db.execute (
"INSERT INTO Produto ('id', 'nome', 'descrição', 'preço',
'imagem') valores (?, ?, ?, ?, ?)",
[5, "Pendrive", "Pendrive é um meio de armazenamento útil", 100, "pendrive.png"]);
aguarde db.execute (
"INSERT INTO Produto ('id', 'nome', 'descrição', 'preço',
'imagem') valores (?, ?, ?, ?, ?)",
[6, "Unidade de disquete", "A unidade de disquete é um meio de armazenamento de
resgate útil", 20, "floppy.png"]);
});
}
131
Machine Translated by Google
Vibração
devolver produtos;
}
resultado de retorno;
}
resultado de retorno;
}
132
Machine Translated by Google
Vibração
}
}
void principal() {
runApp(MyApp(produtos: SQLiteDbProvider.db.getAllProducts()));
}
• Aqui, usamos o método getAllProducts para buscar todos os produtos do banco de dados.
• Execute o aplicativo e veja os resultados. Será semelhante ao exemplo anterior, Acessando a API de serviço do produto,
exceto que as informações do produto são armazenadas e obtidas do banco de dados SQLite local.
Cloud Firestore
Firebase é uma plataforma de desenvolvimento de aplicativos BaaS. Ele fornece muitos recursos para acelerar o
desenvolvimento de aplicativos móveis, como serviço de autenticação, armazenamento em nuvem, etc.. Um dos
principais recursos do Firebase é o Cloud Firestore, um banco de dados NoSQL em tempo real baseado em nuvem.
Flutter fornece um pacote especial, cloud_firestore para programar com Cloud Firestore. Vamos criar uma loja de produtos
online no Cloud Firestore e criar um aplicativo para acessar a loja de produtos.
classe Produto {
nome da string final;
descrição final da String;
preço interno final;
imagem final da String;
• Copie a pasta assets de product_rest_app para product_firebase_app e adicione assets dentro do arquivo
pubspec.yaml
vibração:
133
Machine Translated by Google
Vibração
ativos:
- assets/appimages/floppy.png
- ativos/appimages/iphone.png
- ativos/appimages/laptop.png
- assets/appimages/pendrive.png
- ativos/appimages/pixel.png
- ativos/appimages/tablet.png
dependências:
nuvem_firestore: ^0.9.13+1
• O Android Studio alertará que o pubspec.yaml foi atualizado conforme mostrado aqui:
• Clique na opção Obter dependências. O Android Studio obterá o pacote da Internet e o configurará
adequadamente para o aplicativo.
• Depois que a conta do Firebase for criada, ela será redirecionada para a página de visão geral do projeto.
Ele lista todos os projetos baseados no Firebase e oferece uma opção para criar um novo projeto.
• Insira o banco de dados do aplicativo de produtos como nome do projeto e clique na opção Criar projeto.
• Clique em Visão geral do projeto. Ele abre a página de visão geral do projeto.
• Clique no ícone do Android. Isso abrirá as configurações do projeto específicas para o desenvolvimento do Android.
• Baixe google_service.json e mova-o para o diretório android/app do projeto. Este arquivo é a conexão entre
nosso aplicativo e o Firebase.
134
Machine Translated by Google
Vibração
buildscript
{ repositórios { // ...
dependências { // ...
classpath
'com.google.gms:google-services:3.2.1' // novo
}
}
Aqui, o plugin e o caminho da classe são usados para fins de leitura do arquivo google_service.json.
android
{ configuração padrão {
...
multiDexEnabled verdadeiro
}
...
}
dependências {
...
compilar 'com.android.support:multidex:1.0.3'
}
Essa dependência permite que o aplicativo Android use várias funcionalidades dex.
• Clique em Adicionar coleção. Insira o produto como nome da coleção e clique em Avançar.
135
Machine Translated by Google
Vibração
• Abra o arquivo main.dart e importe o arquivo do plugin Cloud Firestore e remova o pacote http.
importar 'pacote:cloud_firestore/cloud_firestore.dart';
Stream<QuerySnapshot> fetchProducts() {
retornar Firestore.instance.collection('produto').snapshots();
}
• O Cloud Firestore fornece a coleta através do conceito Dart Stream e assim modifica o tipo de produto no widget MyApp
e MyHomePage de Future<list<Product>> para Stream<QuerySnapshot>.
136
Machine Translated by Google
Vibração
@sobrepor
Construção de widget (contexto BuildContext)
{ return
Scaffold( appBar: AppBar(title: Text("Navegação do produto")),
body:
Center( child: StreamBuilder<QuerySnapshot>( stream:
produtos, construtor:
(contexto, instantâneo) {
if (instantâneo.hasError) imprimir(instantâneo.error);
if(snapshot.hasData)
{ List<DocumentSnapshot> documentos = snapshot.data.documents;
List<Produto> itens = List<Produto>();
itens.add(Product.fromMap(document.data));
}
Center(filho: CircularProgressIndicator());
} }, ), ));
}
• Por fim, execute o aplicativo e veja o resultado. Como usamos as mesmas informações do produto do
aplicativo SQLite e alteramos apenas o meio de armazenamento, o aplicativo resultante parece idêntico
ao aplicativo SQLite .
137
Machine Translated by Google
Hoje em dia, as aplicações móveis são utilizadas por clientes de diferentes países e, como resultado, as aplicações são
obrigadas a exibir o conteúdo em diferentes idiomas. Permitir que um aplicativo funcione em vários idiomas é chamado de
Internacionalização do aplicativo.
Para que um aplicativo funcione em idiomas diferentes, ele deve primeiro encontrar a localidade atual
do sistema no qual o aplicativo está sendo executado e, em seguida, mostrar seu conteúdo nessa
localidade específica, e esse processo é chamado de Localização.
A estrutura Flutter fornece três classes base para localização e extensas classes de utilitários derivadas de classes base
para localizar um aplicativo.
• Locale - Locale é uma classe usada para identificar o idioma do usuário. Por exemplo, en-us
identifica o inglês americano e pode ser criado como:
• Localizações - Localizações é um widget genérico usado para definir o local e os recursos localizados de seu
filho.
class CustomLocalizations {
CustomLocalizations(this.locale);
localidade final;
138
Machine Translated by Google
Vibração
• Aqui, CustomLocalizations é uma nova classe customizada criada especificamente para obter determinado conteúdo
localizado (título e mensagem) para o widget. do método usa a classe Localizations para retornar a nova classe
CustomLocalizations.
• LocalizationsDelegate<T> - LocalizationsDelegate<T> é uma classe de fábrica por meio da qual o widget Localizations é
carregado. Possui três métodos substituíveis:
@sobrepor
bool isSupported(Locale locale) => ['en',
'es'].contains(locale.languageCode);
• load - Aceita uma localidade e começa a carregar os recursos para a localidade especificada.
@sobrepor
Future<CustomLocalizations> load(Locale locale) {
retornar
SynchronousFuture<CustomLocalizations>(CustomLocalizations(locale));
}
Aqui, o método load retorna CustomLocalizations. As CustomLocalizations retornadas podem ser usadas para
obter valores de título e mensagem em inglês e espanhol.
@sobrepor
bool deveriaReload(CustomLocalizationsDelegate antigo) => falso;
@sobrepor
bool isSupported(Locale locale) => ['en',
'es'].contains(locale.idiomaCode);
@sobrepor
Future<CustomLocalizations> load(Locale locale) {
retornar
SynchronousFuture<CustomLocalizations>(CustomLocalizations(locale));
139
Machine Translated by Google
Vibração
@sobrepor
bool deveriaReload(CustomLocalizationsDelegate antigo) => falso;
}
Em geral, os aplicativos Flutter são baseados em dois widgets de nível raiz, MaterialApp ou WidgetsApp. Flutter fornece localização
pronta para ambos os widgets e eles são MaterialLocalizations e WidgetsLocaliations. Além disso, o Flutter também fornece
delegados para carregar MaterialLocalizations e GlobalMaterialLocalizations.delegate respectivamente.
WidgetsLocaliations e eles e são
GlobalWidgetsLocalizations.delegate
Vamos criar um aplicativo simples habilitado para internacionalização para testar e compreender o conceito.
• Flutter suporta a internacionalização usando o pacote flutter exclusivo, flutter_localizations. A ideia é separar o conteúdo
localizado do SDK principal.
Abra pubspec.yaml e adicione o código abaixo para habilitar o pacote de internacionalização:
dependências:
vibração:
SDK: vibração
flutter_localizações:
SDK: vibração
• Clique na opção Obter dependências. O Android Studio obterá o pacote da Internet e o configurará adequadamente
para o aplicativo.
importar 'pacote:flutter_localizations/flutter_localizations.dart';
importar 'pacote:flutter/foundation.dart' mostrar SynchronousFuture;
class CustomLocalizations {
CustomLocalizations(this.locale);
localidade final;
140
Machine Translated by Google
Vibração
}, };
@override
bool isSupported(Locale locale) => ['en',
'es'].contains(locale.idiomaCode);
@sobrepor
Future<CustomLocalizations> load(Locale locale) {
retornar
SynchronousFuture<CustomLocalizations>(CustomLocalizations(locale));
}
@override
bool deveriaReload(CustomLocalizationsDelegate antigo) => falso;
}
• Aqui, CustomLocalizations é criado para oferecer suporte à localização de título e mensagem no aplicativo
e CustomLocalizationsDelegate é usado para carregar CustomLocalizations.
localizaçõesDelegados: [const
CustomLocalizationsDelegate(),
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
locais suportados: [ const
Locale('en', ''),
141
Machine Translated by Google
Vibração
@sobrepor
Construção de widget (contexto BuildContext) {
retornar Andaime(
appBar: AppBar(
título: Texto (CustomLocalizations
.of(contexto)
.título),
),
corpo: Centro (
filho: Coluna (
mainAxisAlignment: MainAxisAlignment.center,
filhos: <Widget>[
Texto(
Localizações personalizadas
.of(contexto)
.mensagem,
),
],
),
),
);
}
• Feche o aplicativo. Vá para Configurações -> Sistema -> Idiomas e entrada ->
Línguas*
• Clique em Adicionar uma opção de idioma e selecione Espanhol. Isso instalará o idioma espanhol e o
listará como uma das opções.
• Selecione Espanhol e mova-o acima do Inglês. Isso definirá o espanhol como primeiro idioma e tudo
será alterado para texto em espanhol.
• Podemos reverter o idioma para inglês movendo a opção Inglês acima do espanhol
opção na configuração.
142
Machine Translated by Google
Vibração
Vamos criar um novo aplicativo localizado usando o pacote intl e entender o conceito.
dependências:
vibração:
SDK: vibração
intl: ^0.15.7
intl_translation: ^0.17.3
143
Machine Translated by Google
Vibração
• O Android Studio exibirá o alerta conforme mostrado abaixo informando que o pubspec.yaml
é atualizada.
• Clique na opção Obter dependências. O Android Studio obterá o pacote da Internet e o configurará
adequadamente para o aplicativo.
importar 'pacote:intl/intl.dart';
class CustomLocalizations {
static Future<CustomLocalizations> load(Locale locale) {
final String nome = locale.countryCode.isEmpty? locale.idiomaCode: locale.toString(); string final
localeName =
Intl.canonicalizedLocale(nome);
retornar inicializeMessages(localeName).then((_) {
Intl.defaultLocale = localeName; return
CustomLocalizations(); });
}
}
@sobrepor
144
Machine Translated by Google
Vibração
@sobrepor
Future<CustomLocalizations> load(Locale locale) {
retornar CustomLocalizations.load(locale);
}
@sobrepor
bool deveriaReload(CustomLocalizationsDelegate antigo) => falso;
}
importar 'l10n/messages_all.dart';
• Aqui, o comando irá gerar, arquivo intl_message.arb, um modelo para criar mensagem em localidade diferente. O
conteúdo do arquivo é o seguinte:
{
"@@last_modified": "2019-04-19T02:04:09.627551",
"título": "Demonstração",
"@título": {
"description": "Título da aplicação Demo",
"tipo": "texto",
"espaços reservados": {}
},
"mensagem": "Olá mundo",
"@mensagem": {
"description": "Mensagem para a aplicação Demo",
"tipo": "texto",
"espaços reservados": {}
}
}
• Copie intl_message.arb e crie um novo arquivo, intl_es.arb e altere o conteúdo para o idioma espanhol conforme
mostrado abaixo:
145
Machine Translated by Google
Vibração
{
"@@last_modified": "2019-04-19T02:04:09.627551", "title":
"Manifestação", "@title":
{ "description":
"Título para a aplicação Demo", "type": "text ", "espaços reservados":
{} }, "message": "Olá
Mundo", "@message": {
}
}
• Agora, execute o seguinte comando para criar o arquivo de mensagem final, messages_all.dart
146
Machine Translated by Google
O teste é uma fase muito importante no ciclo de vida de desenvolvimento de uma aplicação. Isso garante que o aplicativo
seja de alta qualidade. O teste requer planejamento e execução cuidadosos. É também a fase mais demorada do
desenvolvimento.
A linguagem Dart e a estrutura Flutter fornecem amplo suporte para o teste automatizado de um aplicativo.
Tipos de teste
Geralmente, três tipos de processos de teste estão disponíveis para testar completamente um aplicativo.
Eles são os seguintes:
Teste de unidade
O teste de unidade é o método mais fácil de testar um aplicativo. Baseia-se em garantir a correção de um trecho de código
(uma função, em geral) ou de um método de uma classe. Porém, não reflete o ambiente real e, posteriormente, é a menor
opção para encontrar os bugs.
Teste de widget
O teste de widget é baseado em garantir a exatidão da criação, renderização e interação do widget com outros widgets
conforme esperado. Ele vai um passo além e fornece um ambiente quase em tempo real para encontrar mais bugs.
Teste de integração
O teste de integração envolve testes de unidade e testes de widget junto com componentes externos do aplicativo, como
banco de dados, serviço da web, etc.. Ele simula ou zomba do ambiente real para encontrar quase todos os bugs, mas é o
processo mais complicado.
Flutter fornece suporte para todos os tipos de testes. Ele fornece suporte amplo e exclusivo para testes de widgets. Neste
capítulo, discutiremos detalhadamente os testes de widgets.
Teste de widget
A estrutura de teste Flutter fornece o método testWidgets para testar widgets. Aceita dois argumentos:
• Descrição de teste
• Código de teste
147
Machine Translated by Google
Vibração
Etapas envolvidas
O teste de widget envolve três etapas distintas:
• WidgetTester é a classe fornecida pela estrutura de testes Flutter para construir e renderizar o widget.
O método pumpWidget da classe WidgetTester aceita qualquer widget e o renderiza no ambiente
de teste.
• A estrutura Flutter oferece muitas opções para encontrar os widgets renderizados no ambiente de
teste e geralmente são chamados de Finders. Os localizadores usados com mais frequência
são find.text, find.byKey e find.byWidget
• find.text encontra o widget que contém o texto especificado.
find.text('Olá')
find.byKey('home')
encontrar.byWidget(homeWidget)
• A estrutura Flutter oferece muitas opções para combinar o widget com o widget esperado e
normalmente são chamadas de Matchers. Podemos usar o método expect fornecido pela estrutura
de teste para combinar o widget, que encontramos na segunda etapa, com nosso widget esperado,
escolhendo qualquer um dos matchers. Alguns dos matchers importantes são os seguintes:
expect(find.text('Olá'), findOneWidget);
148
Machine Translated by Google
Vibração
expect(find.text('Salvar'), findWidgets);
esperar(encontrar.text('Salvar'), encontraNWidgets(2));
expect(find.text('Olá'), findOneWidget);
});
Aqui, renderizamos um widget MaterialApp com o texto Hello usando o widget Text em seu corpo.
Em seguida, usamos find.text para encontrar o widget e, em seguida, combinamos com ele usando findOneWidget.
Exemplo de trabalho
Vamos criar um aplicativo flutter simples e escrever um teste de widget para entender melhor as etapas
envolvidas e o conceito.
• Abra widget_test.dart na pasta de teste. Ele tem um exemplo de código de teste conforme fornecido abaixo:
149
Machine Translated by Google
Vibração
• Vamos tocar novamente no botão de incremento do contador e depois verificar se o contador aumentou para dois.
aguarde tester.tap(find.byIcon(Icons.add));
aguarde tester.pump();
esperar(encontrar.text('2'), encontraOneWidget);
• Clique em testes na opção widget_test.dart. Isso executará o teste e reportará o resultado na janela de resultados.
150
Machine Translated by Google
Este capítulo explica como implantar o aplicativo Flutter nas plataformas Android e iOS.
Aplicativo Android
• Altere o nome do aplicativo usando a entrada android:label no arquivo de manifesto do Android.
Arquivo de manifesto do aplicativo Android, AndroidManifest.xml está localizado em <app dir>/android/
app/src/main. Ele contém detalhes completos sobre um aplicativo Android.
Podemos definir o nome do aplicativo usando a entrada android:label.
cd /caminho/para/meu/aplicativo
apk de construção de vibração
instalação de vibração
• Publique o aplicativo no Google Playstore criando um appbundle e envie-o para o Playstore usando
métodos padrão.
Aplicativo iOS
• Registre o aplicativo iOS no App Store Connect usando o método padrão. Salve o =Bundle ID usado
ao registrar o aplicativo.
• Atualize o nome de exibição na configuração do projeto XCode para definir o nome do aplicativo.
151
Machine Translated by Google
Vibração
• Atualize o identificador do pacote na configuração do projeto XCode para definir o ID do pacote, que
usado na etapa 1.
• Teste o aplicativo enviando o arquivo IPA do aplicativo para o TestFlight usando o método padrão.
• Por fim, envie o aplicativo para a App Store usando o método padrão.
152
Machine Translated by Google
Vibração
19. Flutter – Ferramentas de Desenvolvimento
Este capítulo explica detalhadamente as ferramentas de desenvolvimento do Flutter. A primeira versão estável do kit de
ferramentas de desenvolvimento multiplataforma foi lançada em 4 de dezembro de 2018, Flutter 1.0.
Bem, o Google está trabalhando continuamente nas melhorias e no fortalecimento da estrutura Flutter com diferentes
ferramentas de desenvolvimento.
Conjuntos de widgets
O Google atualizou os conjuntos de widgets Material e Cupertino para fornecer qualidade perfeita em pixels no design dos
componentes. A próxima versão do flutter 1.2 será projetada para suportar eventos de teclado de desktop e suporte para
passar o mouse.
• Assistente de código - Quando quiser verificar opções, você pode usar Ctrl+Espaço para obter uma
lista de opções de conclusão de código.
• Correção rápida - Ctrl+. é uma ferramenta de correção rápida para ajudar a corrigir o código.
• Atalhos de depuração.
• Reinicializações a quente
Dart DevTools
Podemos usar Android Studio ou Visual Studio Code, ou qualquer outro IDE para escrever nosso código e instalar plugins. A
equipe de desenvolvimento do Google está trabalhando em mais uma ferramenta de desenvolvimento chamada Dart DevTools.
É um pacote de programação baseado na web. Suporta plataformas Android e iOS. É baseado na visualização da linha do
tempo para que os desenvolvedores possam analisar facilmente seus aplicativos.
Instale DevTools
Para instalar o DevTools, execute o seguinte comando em seu console:
Resolvendo dependências...
+ argumentos 1.5.1
+ assíncrono 2.2.0
153
Machine Translated by Google
Vibração
+ código de caracteres
1.1.2 + espelho de código 0.5.3+5.44.0
+ coleção 1.14.11
+ converter 2.1.1 +
ferramentas de desenvolvimento 0.0.16
+ js 0.6.1+1 + meta
1.1.7
+ mímica 0.9.6+2
..................
..................
Executar servidor
http://localhost:9100/?port=9200
154
Machine Translated by Google
Vibração
Flutter SDK
Para atualizar o Flutter SDK, use o seguinte comando:
atualização de vibração
Inspetor de vibração
Ele é usado para explorar árvores de widgets flutuantes. Para conseguir isso, execute o comando abaixo em
seu console,
155
Machine Translated by Google
Vibração
Para recarregar as alterações durante a execução, pressione "r". Para reiniciar a quente (e reconstruir o estado),
pressione "R".
Um depurador e criador de perfil do Observatory no iPhone X está disponível em: http://127.0.0.1:50399/
Para uma mensagem de ajuda mais detalhada, pressione "h". Para desconectar, pressione “d”; para sair, pressione "q".
156
Machine Translated by Google
Neste capítulo, aprenderemos como escrever um aplicativo móvel completo, despesas_calculadora. O objetivo da calculadora
de despesas é armazenar nossas informações de despesas. O recurso completo do aplicativo é o seguinte:
• Lista de despesas
Vamos programar o aplicativo gastos_calculator usando os recursos avançados do framework Flutter mencionados abaixo.
• Programação de formulário
dependências:
vibração:
SDK: vibração
sqflite: ^1.1.0
path_provider: ^0.5.0+1
scoped_model: ^1.0.1 intl:
qualquer
• Clique na opção Obter dependências. O Android Studio obterá o pacote da Internet e o configurará adequadamente
para o aplicativo.
157
Machine Translated by Google
Vibração
• Adicione novo arquivo, Expense.dart para criar a classe Expense. A classe de despesas terá as propriedades e
métodos abaixo.
• fromMap - Usado para mapear o campo da tabela do banco de dados para a propriedade no
dados['quantidade'],
DateTime.parse(dados['data']),
dados['categoria']
);
}
• toMap - Usado para converter o objeto de despesa em Dart Map, que pode ser usado posteriormente
na programação de banco de dados
importar 'pacote:intl/intl.dart';
classe Despesa
{ final int id; valor
final duplo; data final
DateTime; categoria String
final;
158
Machine Translated by Google
Vibração
dados['quantidade'],
DateTime.parse(dados['data']),
dados['categoria'] );
• Adicione novo arquivo, Database.dart para criar a classe SQLiteDbProvider. O objetivo da classe SQLiteDbProvider
é o seguinte:
• Obtenha todas as despesas disponíveis no banco de dados usando o método getAllExpenses. Isto
será usado para listar todas as informações de despesas do usuário.
despesas de devolução;
}
• Obtenha informações de despesas específicas com base na identidade de despesas disponível no banco
de dados usando o método getExpenseById. Ele será usado para mostrar informações de despesas
específicas ao usuário.
159
Machine Translated by Google
Vibração
• Adicione novas informações de despesas ao banco de dados usando o método insert. Ele vai
ser usado para adicionar novas entradas de despesas no aplicativo pelo usuário.
);
• Atualize as informações de despesas existentes usando o método de atualização. Ele será utilizado
para editar e atualizar o lançamento de despesas existentes disponíveis no sistema pelo usuário.
resultado de retorno;
}
• Exclua informações de despesas existentes usando o método delete. Será utilizado para retirar o
lançamento de despesas existente disponível no sistema pelo usuário.
160
Machine Translated by Google
Vibração
importar 'Despesa.dart';
classe SQLiteDbProvider
{ SQLiteDbProvider._();
initDB() assíncrono {
DiretóriodocumentsDirectory = aguarda getApplicationDocumentsDirectory(); String caminho =
join(documentsDirectory.path, "ExpenseDB2.db"); return aguarda
openDatabase( caminho, versão:
1,
onOpen: (db)
{}, onCreate: (banco
de dados de banco de dados, versão int) async {
aguarde db.execute
("INSERT INTO Expense ('id', 'quantia', 'data', 'categoria') valores (?, ?, ?, ?)", [1, 1000,
'2019-04-01 10
:00:00', "Comida"]);
161
Machine Translated by Google
Vibração
"pixel.png"]);
aguarde db.execute (
"INSERT INTO Produto ('id', 'nome', 'descrição', 'preço',
'imagem') valores (?, ?, ?, ?, ?)",
[3, "Laptop", "Laptop é a ferramenta de desenvolvimento mais produtiva", 2000,
"laptop.png"]);
aguarde db.execute (
"INSERT INTO Produto ('id', 'nome', 'descrição', 'preço',
'imagem') valores (?, ?, ?, ?, ?)",
[4, "Tablet", "Laptop é a ferramenta de desenvolvimento mais produtiva", 1500,
"tablet.png"]);
aguarde db.execute (
"INSERT INTO Produto ('id', 'nome', 'descrição', 'preço',
'imagem') valores (?, ?, ?, ?, ?)",
[5, "Pendrive", "iPhone é o telefone estilista de todos os tempos", 100,
"pendrive.png"]);
aguarde db.execute (
"INSERT INTO Produto ('id', 'nome', 'descrição', 'preço',
'imagem') valores (?, ?, ?, ?, ?)",
[6, "Floppy Drive", "iPhone é o telefone estilista de todos os tempos", 20,
"floppy.png"]);
*/
});
}
despesas de devolução;
}
162
Machine Translated by Google
Vibração
var id = maxIdResult.first["last_inserted_id"];
resultado de retorno;
}
• Aqui,
• Crie um novo arquivo, ExpenseListModel.dart para criar ExpenseListModel. O objetivo do modelo é manter na memória
as informações completas dos gastos do usuário e atualizar a interface do usuário da aplicação sempre que houver
alteração de gastos do usuário na memória. É baseado na classe Model do pacote scoped_model. Possui as
seguintes propriedades e métodos:
• items - getter para _items como UnmodifiableListView<Expense> para evitar alterações inesperadas
ou acidentais na lista.
163
Machine Translated by Google
Vibração
valor de devolução;
}
• load - Utilizado para carregar as despesas completas do banco de dados e na variável _items. Ele
também chama notifyListeners para atualizar a IU.
void load()
{ Future<List<Despesa>> list = SQLiteDbProvider.db.getAllExpenses();
notificarListeners(); });
}
}
retornar nulo;
}
• add - Usado para adicionar um novo item de despesa na variável _items, bem como no banco de
dados. Ele também chama notifyListeners para atualizar a IU.
notificarListeners(); });
• add - Usado para adicionar um novo item de despesa na variável _items, bem como no banco de dados.
Ele também chama notifyListeners para atualizar a IU.
164
Machine Translated by Google
Vibração
SQLiteDbProvider.db.update(item); quebrar;
}
}
if(encontrado) notifyListeners();
}
• delete - Usado para remover um item de despesa existente na variável _items, bem como
do banco de dados. Ele também chama notifyListeners para atualizar a IU.
SQLiteDbProvider.db.delete(item.id);
_items.removeAt(i);
quebrar;
}
}
if(encontrado) notifyListeners();
}
ExpenseListModel() { this.load(); }
165
Machine Translated by Google
Vibração
valor de devolução;
}
void load()
{ Future<List<Despesa>> list =
SQLiteDbProvider.db.getAllExpenses();
notificarListeners(); });
}
}
retornar nulo;
}
notificarListeners(); });
SQLiteDbProvider.db.update(item); quebrar;
}
}
if(encontrado) notifyListeners();
}
166
Machine Translated by Google
Vibração
SQLiteDbProvider.db.delete(item.id);
_items.removeAt(i);
quebrar;
}
}
if(encontrado) notifyListeners();
}
}
importar 'Despesa.dart';
void main()
{ despesas finais = ExpenseListModel();
runApp(ScopedModel<ExpenseListModel>( modelo:
despesas, filho:
MyApp(), ));
• Aqui,
• ScopedModel fornece informações de despesas durante todo o ciclo de vida da aplicação e garante a
manutenção do estado da aplicação em qualquer instância. Isso nos permite usar
StatelessWidget em vez de StatefulWidget.
167
Machine Translated by Google
Vibração
primárioSwatch: Colors.blue, ),
}
}
• Crie o widget MyHomePage para exibir todas as informações de despesas do usuário junto com as despesas
totais na parte superior. O botão flutuante no canto inferior direito será usado para adicionar novas
despesas.
@override
Widget build (contexto BuildContext) { return
Scaffold( appBar:
AppBar( title:
Text(this.title), ), body:
ScopedModelDescendant<ExpenseListModel>( construtor:
(contexto, filho, despesas) { return ListView.separated(
); } else
{ índice = índice - 1;
return Dismissible( chave:
Key(expenses.items[index].id.toString()), onDismissed: (direção)
{
despesas.delete(despesas.items[índice]);
Scaffold.of(context).showSnackBar(SnackBar( content:
Text("Item com id, " +
despesas.items[index].id.toString()
+
"é descartado")));
},
filho: ListTile( onTap: ()
{ Navigator.push( context,
MaterialPageRoute( builder:
(context) => FormPage( id:
despesas.itens[índice].id,
168
Machine Translated by Google
Vibração
},
inicial: Icon(Icons.monetization_on), final:
Icon(Icons.keyboard_arrow_right),
título: Texto(despesas.items[índice].categoria
+
":" +
ScopedModelDescendant<ExpenseListModel>( construtor:
(contexto, filho, despesas) { return
FloatingActionButton( onPressed: () {
Navigator.push( contexto,
MaterialPageRoute( construtor:
(contexto) =>
ScopedModelDescendant<ExpenseListModel>(
construtor: (contexto, filho, despesas) { return
FormPage(id: 0,
}
}
• Aqui,
169
Machine Translated by Google
Vibração
• O widget dispensável é usado para excluir a entrada de despesas usando o gesto de deslizar.
• O Navigator é usado para abrir a interface de edição de um lançamento de despesas. Pode ser ativado por
tocando em uma entrada de despesas.
• Crie um widget FormPage. A finalidade do widget FormPage é adicionar ou atualizar uma entrada de despesas.
Ele também lida com a validação de entrada de despesas.
ID interno final;
despesas finais de ExpenseListModel;
@sobrepor
_FormPageState createState() => _FormPageState(id: id, despesas: despesas); }
ID interno final;
despesas finais de ExpenseListModel;
valor duplo;
DataHora _data;
String _categoria;
void _submit() {
formulário final = formKey.currentState;
if (form.validate()) {form.save();
se (este.id == 0)
despesas.add(Despesa(0, _quantia, _data, _categoria)); senão
Navigator.pop(contexto);
}
}
@sobrepor
Construção de widget (contexto BuildContext)
{ return Scaffold (
key: scaffoldKey,
appBar: AppBar( title:
Text('Inserir detalhes da despesa'),
170
Machine Translated by Google
Vibração
),
corpo:
Padding( preenchimento: const EdgeInsets.all(16.0), filho:
Form( chave:
formKey, filho:
Column( filhos:
[ TextFormField( estilo:
TextStyle(fontSize: 22), decoração: const
InputDecoration( ícone: const Icon(Icons.monetization_on),
labelText: 'Quantidade', labelStyle: TextStyle(fontSize:
18)),
validador: (val) {
Padrão padrão = r'^[1-9]\d*(\.\d+)?$'; RegExp regex = novo
RegExp(padrão); if (!regex.hasMatch(val)) return 'Digite um
número válido'; outro
retornar nulo;
},
valor inicial:
id == 0? '' : despesas.byId(id).amount.toString(), onSaved: (val) =>
_amount = double.parse(val), ), TextFormField( estilo: TextStyle(fontSize:
const
InputDecoration( ícone: const Icon(Icons.category),
labelText:
: despesas.byId(id).categoria.toString(),
171
Machine Translated by Google
Vibração
),
RaisedButton( onPressed:
_submit, filho: new
Text('Enviar'), ), ], ), ), ), );
}
}
• Aqui,
• a propriedade validator de TextFormField é usada para validar o elemento do formulário junto com
Padrões RegEx.
• A função _submit é usada junto com o objeto de despesas para adicionar ou atualizar as despesas no banco de dados.
importar 'Despesa.dart';
void principal() {
despesas finais = ExpenseListModel();
runApp(ScopedModel<ExpenseListModel>( modelo:
despesas, filho:
MyApp(), ));
'Calculadora de despesas'), );
}
}
172
Machine Translated by Google
Vibração
@override
Widget build (contexto BuildContext) { return Scaffold( appBar:
AppBar( title:
Text(this.title), ), body:
); } else
{ índice = índice - 1; return
Dismissible( chave:
Key(expenses.items[index].id.toString()), onDismissed: (direção) {
despesas.delete(despesas.items[índice]);
dispensado")));
},
filho: ListTile( onTap: ()
{ Navigator.push( context,
MaterialPageRoute( construtor:
(context) => FormPage(
id: despesas.items[index].id,
despesas: despesas, )));
},
inicial: Icon(Icons.monetization_on), final:
Icon(Icons.keyboard_arrow_right), título: Text(expenses.items[index].category
+
": " +
despesas.items[index].formattedDate, estilo:
TextStyle(fontSize: 18, fontStyle: FontStyle.italic),)));
173
Machine Translated by Google
Vibração
return Divisor(); }, ); }, ),
Navigator.push
(contexto,
MaterialPageRoute
(construtor: (contexto) =>
ScopedModelDescendant<ExpenseListModel>( construtor:
(contexto, filho, despesas) { return FormPage( id: 0,
}
}
ID interno final;
despesas finais de ExpenseListModel;
@sobrepor
_FormPageState createState() => _FormPageState(id: id, despesas: despesas); }
ID interno final;
despesas finais de ExpenseListModel;
valor duplo;
DataHora _data;
String _categoria;
174
Machine Translated by Google
Vibração
void _submit() {
formulário final = formKey.currentState;
if (form.validate()) {form.save();
se (este.id == 0)
despesas.add(Despesa(0, _quantia, _data, _categoria)); senão
Navigator.pop(contexto);
}
}
@sobrepor
Construção de widget (contexto BuildContext) { return
Scaffold (
key: scaffoldKey, appBar:
AppBar( title: Text('Inserir
detalhes da despesa'), ), body: Padding( padding: const
EdgeInsets.all(16.0),
child: Form( key: formKey, child: Column( children:
[ TextFormField( estilo:
TextStyle(fontSize:
22), decoração:
const
InputDecoration( ícone: const
Icon(Icons.monetization_on), labelText: 'Quantidade',
labelStyle: TextStyle(fontSize:
18)),
validador: (val) {
Padrão padrão = r'^[1-9]\d*(\.\d+)?$'; RegExp regex = novo
RegExp(padrão); if (!regex.hasMatch(val)) return 'Digite um
número válido'; outro
retornar nulo;
},
valor inicial:
id == 0? '' : despesas.byId(id).amount.toString(), onSaved: (val) =>
_amount = double.parse(val), ), TextFormField( estilo: TextStyle(fontSize:
175
Machine Translated by Google
Vibração
const
InputDecoration( ícone: const Icon(Icons.category),
labelText:
: despesas.byId(id).categoria.toString(),
),
RaisedButton( onPressed:
_submit, filho: new
Text('Enviar'), ), ], ), ), ), );
}
}
176
Machine Translated by Google
Vibração
177
Machine Translated by Google
Vibração
178
Machine Translated by Google
Vibração
179
Machine Translated by Google
A estrutura Flutter faz um ótimo trabalho ao fornecer uma excelente estrutura para construir aplicativos móveis de uma forma
verdadeiramente independente de plataforma. Ao fornecer simplicidade no processo de desenvolvimento, alto desempenho
no aplicativo móvel resultante, interface de usuário rica e relevante para plataformas Android e iOS, a estrutura Flutter
certamente permitirá que muitos novos desenvolvedores desenvolvam aplicativos móveis de alto desempenho e cheios de
recursos no futuro próximo.
180