Introdução ao Flutter
Desenvolvimento de Aplicativos Móveis
1 Apresentação
Sobre a apostila
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 .
Esta apostila aborda os fundamentos da estrutura do Flutter, a instalação do SDK do Flutter, a configuração do Android Studio para desenvolver aplicativos baseados no Flutter, a arquitetura da estrutura do Flutter e o desenvolvimento de todos os tipos de aplicativos móveis usando a estrutura do Flutter.
Público alvo
Esta apostila l é preparado para profissionais que aspiram fazer carreira na área de aplicativos móveis. Este tutorial destina-se a deixá-lo confortável para começar a usar o framework Flutter e suas várias funcionalidades.
Pré-requisitos
Esta apostila foi escrita assumindo que os leitores já estão cientes sobre o que é um Framework e que os leitores têm um bom conhecimento sobre Programação Orientada a Objetos e conhecimento básico sobre framework Android e programação Dart.
Se você é iniciante em algum desses conceitos, sugerimos que consulte primeiro os tutoriais relacionados a eles, antes de começar com o Flutter.
Em geral, desenvolver um aplicativo móvel é uma tarefa complexa e desafiadora. Existem muitos frameworks disponíveis para desenvolver um aplicativo móvel. O Android fornece um framework nativo baseado na linguagem Java e o iOS fornece um framework nativo baseado na linguagem Objective-C/Shift.
No entanto, para desenvolver um aplicativo compatível com os dois sistemas operacionais, precisamos codificar em duas linguagens diferentes usando duas estruturas diferentes. Para ajudar a superar essa complexidade, existem estruturas móveis que suportam ambos os sistemas operacionais. Essas estruturas variam de uma estrutura de aplicativo móvel híbrida baseada em HTML simples (que usa HTML para a interface do usuário e JavaScript para a lógica do aplicativo) até uma estrutura específica de linguagem complexa (que faz o trabalho pesado de converter código em código nativo). Independentemente de sua simplicidade ou complexidade, esses frameworks sempre apresentam muitas desvantagens, sendo uma das principais desvantagens seu baixo desempenho.
Nesse cenário, o Flutter – um framework simples e de alto desempenho baseado na linguagem Dart, oferece alto desempenho ao renderizar a interface do usuário diretamente na tela do sistema operacional, em vez de por meio do framework nativo.
O Flutter também oferece muitos widgets (UI) prontos para usar para criar um aplicativo moderno. Esses widgets são otimizados para ambientes móveis e projetar o aplicativo usando widgets é tão simples quanto projetar HTML.
2 Introdução ao Flutter
Para ser específico, o aplicativo Flutter é em si um widget. Os widgets Flutter também suportam animações e gestos. A lógica da aplicação é baseada na programação reativa. 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.
Discutiremos a arquitetura completa nos próximos capítulos.
Recursos do Flutter
Flutter framework oferece os seguintes recursos para desenvolvedores:
• Estrutura moderna e reativa.
• Usa a linguagem de programação Dart e é muito fácil de aprender.
• Desenvolvimento rápido.
• Interfaces de usuário bonitas e fluidas.
• Enorme catálogo de widgets.
• Executa a mesma interface do usuário para várias plataformas.
• Aplicativo de alto desempenho.
Vantagens do Flutter
O 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 de 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. Por causa de 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.
• O Flutter oferece ótimas ferramentas para desenvolvedores, com incrível hot reload.
Desvantagens do Flutter
Apesar de suas muitas vantagens, o flutter tem as seguintes desvantagens:
• Por ser codificado em 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 interface do usuário o máximo 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 usando 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.
3 Instalação do Flutter
Instalação no Windows
Nesta seção, veremos 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 SDK do Flutter mais recente.
Por exemplo: Em abril de 2019, a versão é 1.2.1 e o arquivo é flutter_windows_v1.2.1-stable.zip.
Passo 2: Descompacte o arquivo zip em uma pasta, digamos C:flutter
Etapa 3: Atualize o caminho do sistema para incluir o diretório flutter bin.
Etapa 4: Flutter fornece uma ferramenta, flutter doctor para verificar se todos os requisitos de desenvolvimento de flutter são atendidos.
Passo 5: A execução do comando acima analisará o sistema e mostrará seu relatório conforme abaixo:
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 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 8: Inicie um emulador Android ou conecte um dispositivo Android real ao sistema.
Passo 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 estúdio do Android, etc.,
• Abra o Android Studio.
• Clique em Arquivo > Configurações > Plug-ins.
• Selecione o plugin Flutter e clique em Instalar.
• Clique em Sim quando solicitado a instalar o plug-in do Dart.
• Reinicie o estúdio Android.
Instalação no MacOS
Para instalar o Flutter no MacOS, você deverá seguir os seguintes passos:
Passo 1 : Vá para 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.1stable.zip.
Passo 2 : Descompacte o arquivo zip em uma pasta, digamos /path/to/flutter
Etapa 3 : Atualize o caminho do sistema para incluir o diretório flutter bin (no arquivo ~/.bashrc).
Etapa 4 : Ative o caminho atualizado na sessão atual usando o comando abaixo e verifique-o também.
Flutter fornece uma ferramenta, flutter doctor para verificar se todos os requisitos de desenvolvimento de flutter são atendidos. É semelhante à contraparte do Windows.
Etapa 5 : Instale o XCode mais recente, se relatado pelo flutter doctor
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 Android ou conecte um dispositivo Android real ao sistema para desenvolver o aplicativo Android.
Etapa 9 : Abra o simulador iOS ou conecte um dispositivo iPhone real ao sistema para desenvolver o aplicativo iOS.
Passo 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 estúdio do Android, etc.,
• Abra o Android Studio.
• Clique em Preferências > Plug-ins .
• Selecione o plugin Flutter e clique em Instalar.
• Clique em Sim quando solicitado a instalar o plug-in do Dart.
• Reinicie o estúdio Android.
4 Criando um Aplicativo Simples
Abrindo o Android Studio
Verifique se você tem o Android Studio instalado no seu computador. Se você não o tiver, você pode baixá-lo no site oficial do Android Studio (https://developer.android.com/studio) e seguir as instruções de instalação.
Após a instalação, procure pelo ícone do Android Studio no seu menu Iniciar ou na área de trabalho. Geralmente, o ícone é um círculo verde com um robô dentro.
Clique duas vezes no ícone do Android Studio para iniciar o programa.
Na primeira execução, você pode ser solicitado a importar configurações do Android Studio anteriormente instalado ou optar por configurações padrão. Escolha a opção desejada e prossiga.
Aguarde alguns momentos enquanto o Android Studio é inicializado. Pode levar algum tempo na primeira vez que você o executa.
Após a inicialização, você verá a tela principal do Android Studio. Aqui, você pode criar um novo projeto, abrir projetos existentes ou acessar recursos e ferramentas adicionais do Android Studio.
Essas são as etapas básicas para abrir o Android Studio no Windows. Certifique-se de ter o Java Development Kit (JDK) instalado no seu sistema, pois o Android Studio requer o JDK para funcionar corretamente.
Criando Projeto Flutter
Para isso, clique em Arquivo -> Novo -> Novo Projeto Flutter
Selecionando uma aplicação Flutter.
Para isso, selecione Flutter Application e clique em Next .
Configurações Básicas
Configure o aplicativo conforme abaixo e clique em Avançar .
• Nome do projeto: hello_app
• Caminho do Flutter SDK: <path_to_flutter_sdk>
• Localização do Projeto: <path_to_project_folder>
• Descrição: aplicativo hello world baseado em Flutter
Configuração do projeto
Defina o domínio da empresa como flutterapp.tutorialspoint.com e clique em Concluir
Insira o domínio da empresa
O Android Studio cria um aplicativo flutter totalmente funcional com funcionalidade mínima. Vamos verificar a estrutura do aplicativo e, em seguida, alterar o código para realizar nossa tarefa.
A estrutura do aplicativo e sua finalidade são as seguintes:
Vários componentes da estrutura do aplicativo são explicados aqui:
• android - código-fonte gerado automaticamente para criar aplicativo android
• ios - Código-fonte gerado automaticamente para criar aplicativo ios
• lib - Pasta principal contendo o código Dart escrito usando o framework flutter
• lib/main.dart - Ponto de entrada do aplicativo Flutter
• test - Pasta contendo código Dart para testar o aplicativo flutter
• test/widget_test.dart - Exemplo de código
• .gitignore - arquivo de controle de versão do Git
• .metadata - gerado automaticamente pelas ferramentas de vibração
• .packages - gerado automaticamente para rastrear os pacotes flutuantes
• .iml - arquivo de projeto usado pelo estúdio Android
• pubspec.yaml - Usado por Pub , gerenciador de pacotes Flutter
• pubspec.lock - Gerado automaticamente pelo gerenciador de pacotes Flutter, Pub
• README.md - Arquivo de descrição do projeto escrito no formato Markdown
Substitua o código dart no arquivo lib/main.dart pelo código abaixo:
Explicando o código dart:
Linha 1: importa o pacote flutter, material . O material é um pacote flutter para criar a interface do 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 a 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 objetivo do método build é criar uma parte da interface do usuário do aplicativo. Aqui, o método build usa MaterialApp , um widget para criar a IU de nível raiz do aplicativo. Ele tem três propriedades: título , tema e home .
- título é o título do aplicativo.
- tema é o tema do widget. Aqui, definimos o azul como a cor geral do aplicativo usando a classe ThemeData e sua propriedade, primarySwatch .
- home é a UI interna do aplicativo, para a qual configuramos outro widget, MyHomePage
Linha 19 - 38 : MyHomePage é igual a MyApp , exceto que retorna o widget Scaffold . Scaffold é um widget de nível superior ao lado do widget MaterialApp usado para criar design de material em conformidade com a interface do usuário. Ele tem duas propriedades importantes, appBar para mostrar o cabeçalho do aplicativo e corpo para mostrar o conteúdo real do aplicativo. AppBar é outro widget para renderizar o cabeçalho do aplicativo e o usamos na propriedade appBar . Na propriedade body , usamos o widget Center , que centraliza o widget filho. Textoé o widget final e mais interno para mostrar o texto e é exibido no centro da tela.
Executando o aplicativo usando Executar -> Executar main.dart
Aplicativo resultante:
5 Arquitetura da Aplicação Flutter
Widgets
O conceito central da estrutura do Flutter é In Flutter, Everything is a widget . Widgets são basicamente componentes de interface do usuário usados para criar a interface do usuário do aplicativo.
No Flutter, o próprio aplicativo é um widget. O aplicativo é o widget de nível superior e sua IU é construída usando um ou mais filhos (widgets), que novamente são construídos usando seus widgets filhos. Esse recurso de composição nos ajuda a criar uma interface de usuário de qualquer complexidade.
Por exemplo, a hierarquia de widgets do aplicativo hello world (criada no capítulo anterior) é especificada no diagrama a seguir:
Os seguintes pontos são dignos de nota:
• MyApp é o widget criado pelo usuário e é construído usando o widget nativo do Flutter, MaterialApp .
• MaterialApp tem uma propriedade home para especificar a interface do usuário da página inicial, que é novamente um widget criado pelo usuário, MyHomePage .
• MyHomePage é construído usando outro widget nativo de vibração, Scaffold .
• Scaffold tem duas propriedades – body e appBar .
• body é usado para especificar sua interface de usuário principal e appBar é usado para especificar sua interface de usuário de cabeçalho.
• A IU do cabeçalho é criada usando o widget nativo de vibração, a AppBar e a IU do corpo são criadas usando o widget Central .
• O widget Center tem uma propriedade, Child , que se refere ao conteúdo real e é construído usando o widget Text .
Gestures (Gestos)
Os widgets do Flutter oferecem suporte à interação por meio de um widget especial, GestureDetector . GestureDetector é um widget invisível com a capacidade de capturar interações do usuário, como tocar, arrastar, etc., de seu widget filho. Muitos widgets nativos do Flutter oferecem suporte à 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.
Concept of State (Conceito de Estado)
Widgets Flutter oferecem suporte à manutenção de estado fornecendo um widget especial, StatefulWidget . O widget precisa ser derivado do widget StatefulWidget para suportar a manutenção do estado e todos os outros widgets devem ser derivados do StatelessWidget . Widgets Flutter são reativos em nativo. Isso é semelhante a reactjs e 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.
Layers (Camadas)
O conceito mais importante da estrutura do Flutter é que a estrutura é agrupada em várias categorias em termos de complexidade e claramente organizada em camadas de complexidade decrescente. Uma camada é construída usando sua próxima camada de nível imediato. A camada superior é o widget específico para Android e iOS . A próxima camada tem todos os widgets nativos de vibração. A próxima camada é a camada de renderização , que é um componente do renderizador de baixo nível e renderiza tudo no aplicativo flutter. As camadas descem para o código específico da plataforma central.
A visão geral de uma camada no Flutter é especificada no diagrama abaixo:
Os pontos a seguir resumem a arquitetura do Flutter:
• No Flutter, tudo é um widget e um widget complexo é composto por widgets já existentes.
• Recursos interativos podem ser incorporados sempre que necessário usando o widget GestureDetector .
• O estado de um widget pode ser mantido sempre que necessário usando o widget StatefulWidget .
• O Flutter oferece design em camadas para que qualquer camada possa ser programada dependendo da complexidade da tarefa.
Discutiremos todos esses conceitos em detalhes nos próximos capítulos.
6 Introdução a Programação Dart
Dart é uma linguagem de programação de uso geral de código aberto. É originalmente desenvolvido pelo Google. Dart é uma linguagem orientada a objetos com sintaxe estilo C. Ele oferece suporte a 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.
O código a seguir mostra um programa Dart simples:
Variáveis e tipos de dados
A variável é chamada de local de armazenamento e os tipos de dados simplesmente se referem ao tipo e tamanho dos dados associados a variáveis e funções.
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 como abaixo:
A linguagem Dart suporta os seguintes tipos de dados:
• Numbers : É usado para representar literais numéricos – Integer e Double.
• Strings : Representa uma sequência de caracteres. Os valores de string são especificados entre aspas simples ou duplas.
• Booleans : Dart usa a palavra-chave bool para representar valores booleanos – true e false.
• Listas e Mapas : É usado para representar uma coleção de objetos. Uma lista simples pode ser definida como abaixo:
A lista mostrada acima produz a lista [1,2,3,4,5].
O mapa pode ser definido como mostrado aqui:
Dinâmico: Se o tipo de variável não estiver definido, então seu tipo padrão é dinâmico. O exemplo a seguir ilustra a variável de tipo dinâmico:
Tomada de Decisão e Loops
Um bloco de tomada de decisão avalia uma condição antes que as instruções sejam executadas. Dart suporta instruções If, If..else e switch.
Os loops são usados para repetir um bloco de código até que uma condição específica seja atendida. Dart suporta for, for..in , while e do..while loops.
Vamos entender um exemplo simples sobre o uso de instruções de controle e loops:
O código acima imprime os números pares de 1 a 10.
Funções
Uma função é um grupo de instruções que juntas executam uma tarefa específica. Vejamos uma função simples no Dart, conforme mostrado aqui:
A função acima adiciona dois valores e produz 7 como saída.
Programação Orientada a Objetos
Dart é uma linguagem orientada a objetos. Ele suporta recursos de programação orientada a objetos, como classes, interfaces, etc.
Uma classe é um projeto para a criação de objetos. Uma definição de classe inclui o seguinte:
• Campos
• Getters e setters
• Construtores
• Funções
Agora, vamos criar uma classe simples usando as definições acima:
7 Introdução ao Widgets
Como aprendemos no capítulo anterior, os 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 é dado abaixo:
Aqui, criamos um novo widget estendendo StatelessWidget .
Observe que o StatelessWidget requer apenas um único método build 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 de Scaffold , que por sua vez chama o método build de AppBar e Center para construir sua interface de usuário.
Finalmente, o método de construção Center chama o método de construção Text .
Para um melhor entendimento, segue abaixo a representação visual do mesmo:
Widget Build Visualization
No Flutter , os widgets podem ser agrupados em várias categorias com base em seus recursos, conforme listado abaixo:
• Widgets específicos da plataforma
• Widgets de layout
• Widgets de manutenção de estado
• Widgets básicos/independentes de plataforma
Vamos discutir cada um deles em detalhes agora.
Widgets específicos da plataforma
O Flutter possui widgets específicos para uma determinada plataforma - Android ou iOS.
Os widgets específicos do Android são projetados de acordo com a diretriz de design de materiais do sistema operacional Android. Os 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 .
Alguns dos widgets de materiais mais usados são os seguintes:
• Andaime
• AppBar
• Barra de Navegação Inferior
• TabBar
• TabBarView
• ListTile
• Botão Levantado
• BotãoAçãoFlutuante
• FlatButton
• ÍconeBotão
• Botão suspenso
• PopupMenuButton
• Barra de botões
• Campo de texto
• Caixa de seleção
• Rádio
• Interruptor
• Controle deslizante
• Selecionadores de data e hora
• SimpleDialog
• Caixa de diálogo Alerta
Alguns dos widgets de Cupertino mais usadossão os seguintes:
• Botão Cupertino
• CupertinoPicker
• CupertinoDatePicker
• CupertinoTimerPicker
• CupertinoNavigationBar
• CupertinoTabBar
• CupertinoTabScaffold
• CupertinoTabView
• CupertinoTextField
• CupertinoDialog
• CupertinoDialogAction
• CupertinoFullscreenDialogTransition
• CupertinoPageScaffold
• CupertinoPageTransition
• CupertinoActionSheet
• CupertinoActivityIndicator
• CupertinoAlertDialog
• CupertinoPopupSurface
• CupertinoSlider
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 Center .
Alguns dos widgets de layout populares são os seguintes:
• Container: Uma caixa retangular decorada com widgets BoxDecoration com fundo, borda e sombra.
• Centralizar: Centralize seu widget filho
• Linha: Organiza seus filhos na direção horizontal.
• Coluna: Disponha seus filhos na direção vertical.
• Pilha: Disponha um sobre o outro.
Veremos os widgets de layout em detalhes no próximo capítulo Introdução aos widgets de layout .
Widgets de manutenção de estado
No Flutter, todos os widgets são derivados de StatelessWidget ou StatefulWidget .
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 ocorre 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 renderizará automaticamente o widget usando novas informações de estado.
Aprenderemos o conceito de widgets StatefulWidget em detalhes no próximo capítulo de gerenciamento de estado
Widgets básicos/independentes de plataforma
O Flutter fornece um grande número de widgets básicos para criar interfaces de usuário simples e complexas de maneira independente da plataforma. Vamos ver alguns dos widgets básicos neste capítulo.
Text (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 essa finalidade é o seguinte:
O widget de texto tem um construtor especial, Text.rich , que aceita o filho do tipo TextSpan para especificar a string com um estilo diferente. O widget TextSpan é recursivo por natureza e aceita TextSpan como seus filhos. O código de exemplo para essa finalidade é o seguinte:
As propriedades mais importantes do widget Texto são as seguintes:
• maxLines, int: Número máximo de linhas a serem exibidas
• overflow, TextOverFlow: Especifique como o estouro visual é tratado usando a classe TextOverFlow
• style, TextStyle: Especifique o estilo da string usandoa classe TextStyle
• textAlign, TextAlign: Alinhamento do texto como direita, esquerda, justificar, etc., usando a classe TextAlign
• textDirection, TextDirection: direção do fluxo do texto, 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 várias fontes e são os seguintes:
• Image - Carregador de imagem genérico usando ImageProvider
• Image.asset - Carrega a imagem dos ativos do projeto flutuante
• Image.file - Carregar imagem da pasta do sistema Image.memory - Carregar imagem da memória
• Image.Network - Carregar imagem da rede
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.
• Crie uma pasta, assets na pasta do projeto e coloque as imagens necessárias.
• Especifique os recursos no pubspec.yaml conforme mostrado abaixo:
• Agora, carregue e exiba a imagem no aplicativo.
• O código-fonte completo do widget MyHomePage do aplicativo hello world e o resultado são os mostrados abaixo:
A imagem carregada é a mostrada abaixo:
As propriedades mais importantes do widget de imagem são as seguintes:
• imagem, ImageProvider: imagem real para carregar
• largura, dupla - Largura da imagem
• altura, duplo - Altura da imagem
• alinhamento, AlignmentGeometry - Como alinhar a imagem dentro de seus limites
Í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:
O código-fonte completo para aplicá-lo no aplicativo hello world é o seguinte:
O ícone carregado é o mostrado abaixo:
8 Introdução aos Layouts
Como o conceito principal do Flutter é Everything is widget , o Flutter incorpora uma funcionalidade de layout de interface do usuário nos próprios widgets. O Flutter fornece muitos widgets especialmente projetados, como Container , Center , Align , etc., apenas com o objetivo de definir a interface do usuário. Widgets construídos compondo outros widgets normalmente usam widgets de layout. Vamos aprender o conceito de layout do Flutter neste capítulo.
Tipo de widgets de layout
Os widgets de layout podem ser agrupados em duas categorias distintas com base em seu filho:
• Widget que suporta uma única criança
• Widget que suporta vários filhos
Vamos aprender os dois tipos de widgets e sua funcionalidade nas próximas seções.
Widgets de filho único
Nesta categoria, os widgets terão apenas um widget como filho e cada widget terá uma funcionalidade de layout especial.
Por exemplo, o widget Center apenas centraliza o widget filho em relação ao widget pai e o widget Container oferece total flexibilidade para colocá-lo filho em qualquer lugar dentro dele usando opções diferentes, como preenchimento, decoração, etc.,
Widgets de filho único são ótimas opções para criar widget de alta qualidade com funcionalidade única, como botão, rótulo, etc.,
O código para criar um botão simples usando o widget Container é o seguinte:
Aqui, usamos dois widgets – um widget de contêiner e um widget de texto . 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 pelo preenchimento fornecido. Aqui, o preenchimento pode ser fornecido pela classe EdgeInsets .
• Alinhar : Alinha seu widget filho dentro de si 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 a partir do canto superior esquerdo.
Alguns dos possíveis valores de offsets são os seguintes:
• FractionalOffset(1.0, 0.0) representa o canto superior direito.
• FractionalOffset(0.0, 1.0) representa a parte inferior esquerda.
• Um exemplo de código sobre compensações é mostrado abaixo:
• FittedBox: dimensiona o widget filho e o posiciona de acordo com o ajuste especificado.
• AspectRatio: tenta dimensionar o widget filho para a proporção especificada
• CaixaConstringida
• Linha de base
• Caixa FractinallySized
• Altura Intrínseca
• Largura Intrínseca
• Caixa Limitada
• Fora do Palco
• Caixa de Transbordo
• SizedBox
• SizedOverflowBox
• Transformar
• CustomSingleChildLayout
Nosso aplicativo hello world está usando 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 junto com recursos de estilo sofisticados.
• Center : Simples, widget de contêiner filho único, que centraliza seu widget filho.
O código modificado do widget MyHomePage e MyApp é o seguinte:
Aqui,
• Widget de contêiner é o widget raiz ou de nível superior. O contêiner é configurado usando as propriedades de decoração e preenchimento para o layout de seu conteúdo.
• BoxDecoration tem muitas propriedades como cor, borda, etc., para decorar o widget Container e aqui a cor é usada 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 é o 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.
O resultado final do código fornecido acima é um exemplo de layout conforme mostrado abaixo:
Vários widgets filhos
Nesta categoria, um determinado widget terá mais de um widget filho e o layout de cada widget é único.
Por exemplo, o widget Row permite a disposição de seus filhos na direção horizontal, enquanto o widget Column permite a disposição de seus filhos na direção vertical. Compondo Row e Column , widgets com qualquer nível de complexidade podem ser construídos.
Vamos aprender alguns dos widgets usados com frequência nesta seção.
• Fila - Permite dispor seus filhos de forma horizontal.
• Coluna - Permite dispor seus filhos de forma vertical.
• ListView - Permite organizar seus filhos como lista.
• GridView - Permite organizar seus filhos como galeria.
• Expandido - Usado para fazer com que os filhos do widget Linha e Coluna ocupem o máximo de área possível.
• Tabela - Widget baseado em tabela.
• Fluxo - Widget baseado em fluxo.
• Pilha - Widget baseado em pilha.
Aplicativo de layout avançado
Nesta seção, vamos aprender como criar uma interface de usuário complexa de listagem de produtos com design personalizado usando widgets de layout filho únicos e múltiplos.
Para tanto, siga a sequência abaixo:
• Crie um novo aplicativo Flutter no estúdio Android, product_layout_app.
• Substitua o código main.dart pelo seguinte código:
• Aqui,
• Criamos o widget MyHomePage estendendo o StatelessWidget em vez do StatefulWidget padrão e, em seguida, removemos o código relevante.
• Agora, crie um novo widget, ProductBox de acordo com o design especificado conforme mostrado abaixo:
• O código da ProductBox é o seguinte:
Observe o seguinte no código:
• ProductBox usou quatro argumentos conforme especificado abaixo:
- nome - Nome do produto o descrição - Descrição do produto o preço - Preço do produto o imagem - Imagem do produto
• ProductBox usa sete widgets integrados conforme especificado abaixo:
- Contêiner o Expandido o Linha o Coluna o Cartão o Texto o Imagem
• ProductBox é projetado usando o widget mencionado acima. A disposiçã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:
• Finalmente, use o widget ProductBox no widget MyHomePage conforme especificado abaixo:
• Aqui, usamos ProductBox como filhos do widget ListView .
• O código completo ( main.dart ) do aplicativo de layout do produto ( product_layout_app ) é o seguinte:
A saída final do aplicativo é a seguinte:
9 Introdução aos Gestures
Gestos
Os Gestures são principalmente uma maneira 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 simples toques na tela do dispositivo móvel até ações mais complexas usadas em aplicativos de jogos.
Alguns dos gestos amplamente utilizados são mencionados aqui:
• Tocar : tocar a superfície do dispositivo com a ponta do dedo por um curto período e depois soltar a ponta do dedo.
• Toque duplo : tocando duas vezes em um curto espaço de tempo.
• Arrastar : Tocar a superfície do dispositivo com a ponta do dedo e, em seguida, mover a ponta do dedo de forma constante e finalmente soltar a ponta do dedo.
• Flick : Semelhante a arrastar, mas de forma mais rápida.
• Apertar : Apertar a superfície do dispositivo usando dois dedos.
• Espalhar/Zoom : Oposto de pinçar.
• Panning : Tocar a superfície do dispositivo com a ponta do dedo e movê-lo em qualquer direção sem soltar a ponta do dedo.
O Flutter fornece um excelente suporte para todos os tipos de gestos por meio 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 despachar vários eventos com base no gesto.
Alguns dos gestos e os eventos correspondentes são dados abaixo:
- Tap (Toque)
- onTapDown
- onTapUp
- onTap
- onTapCancel
- Double tap (Toque duas vezes)
- onDoubleTap
- Long press (Pressione e segure)
- onLongPress
- Vertical drag (Arrasto vertical)
- onVerticalDragStart
- onVerticalDragUpdate
- onVerticalDragEnd
- Horizontal drag (Arrastar horizontal)
- onHorizontalDragStart
- onHorizontalDragUpdate
- onHorizontalDragEnd
- Pan (Panorâmica)
- onPanStart
- onPanUpdate
- onPanEnd
Agora, vamos modificar o aplicativo hello world para incluir o recurso de detecção de gestos e tentar entender o conceito.
• Altere o conteúdo do corpo do widget MyHomePage conforme mostrado abaixo:
• Observe que aqui colocamos owidget GestureDetector acima do widget Text na hierarquia do widget, capturamos o evento onTap e finalmente mostramos uma janela de diálogo.
• Implemente a função *_showDialog* para apresentar uma caixa de diálogo quando o usuário tabular a mensagem hello world . Ele usa o widget genérico showDialog e AlertDialog para criar um novo widget de diálogo. O código é mostrado abaixo:
• O aplicativo será recarregado no dispositivo usando o recurso Hot Reload . Agora, basta clicar na mensagem Hello World e ela mostrará a caixa de diálogo abaixo:
• Agora, feche a caixa de diálogo clicando na opção fechar na caixa de diálogo.
• O código completo (main.dart) é o seguinte:
Por fim, 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 enviará os seguintes eventos:
• PointerDownEvent
• PointerMoveEvent
• PointerUpEvent
• PointerCancelEvent
O Flutter também fornece um pequeno conjunto de widgets para fazer gestos específicos e avançados. Os widgets estão listados abaixo:
• Dismissible (Ignorável): Suporta gesto de movimento para descartar o widget.
• Draggable (Arrastável): Suporta gesto de arrastar para mover o widget.
• LongPressDraggable (Pressão longa arrastável): Suporta o gesto de arrastar para mover um widget, quando seu widget pai também pode ser arrastado.
• DragTarget (Arraste o alvo): aceita qualquer widget arrastável .
• IgnorePointer (Ignorar Ponteiro): Oculta o widget e seus filhos do processo de detecção de gestos.
• AbsorbPointer (Absorver Ponteiro): interrompe o próprio processo de detecção de gestos e, portanto, qualquer widget sobreposto também não pode participar do processo de detecção de gestos e, portanto, nenhum evento é gerado.
• Scrollable (Rolável): Suporta rolagem do conteúdo disponível dentro do widget
10 Gerenciamento de Estado
State Management
Gerenciar o estado em um aplicativo é um dos processos mais importantes e necessários no ciclo de vida de um aplicativo.
Vamos considerar um aplicativo de carrinho de compras simples.
• O usuário fará login usando suas credenciais no aplicativo.
• Uma vez logado o usuário, a aplicação deve manter os detalhes do usuário logado em toda 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 do carrinho em qualquer instância são chamadas de estado do aplicativo nessa 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.
• Ephemeral - Dura alguns segundos como o estado atual de uma animação ou uma única página como a classificação atual de um produto. O Flutter suporta isso por meio do StatefulWidget.
• Estado do aplicativo - Último para todo o aplicativo, como detalhes do usuário logado, informações do carrinho, etc., o Flutter oferece suporte a ele por meio do scoped_model.
Gerenciamento de estado efêmero
Como o aplicativo Flutter é composto por widgets, o gerenciamento de estado também é feito por widgets. O ponto de entrada do gerenciamento de estado é o Statefulwidget. O widget pode ser herdado do Statefulwidget para manter seu estado e o estado de seus filhos. Statefulwidget fornece uma opção para um widget criar um estado, State<T> (onde T é o widget herdado) quando o widget é criado pela primeira vez por meio do método createState e, em seguida, um método, setState para alterar o estado sempre que necessário. A mudança de estado será feita através de gestos. Por exemplo, a classificação de um produto pode ser alterada tocando em uma estrela no widget de classificação.
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:
• Crie o widget RatingBox herdando StatefulWidget
• Crie um estado para RatingBox, _RatingBoxState herdando State<T>
• Substitua o método createState do StatefulWidget para criar o estado, _RatingBoxState
Crie a interface do usuário do widget RatingBox no método de construção de _RatingBoxState. Normalmente, a interface do usuário será feita no método build do próprio widget RatingBox. Mas, quando a manutenção do estado é necessária, precisamos construir a interface do usuário no widget _RatingBoxState. Isso garante a renderização da interface do usuário sempre que o estado do widget for alterado.
Aqui, usamos três estrelas, criadas usando o widget IconButton e as organizamos 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 primeiras duas estrelas serão vermelhas e a última será branca.
• Escreva métodos em _RatingBoxState para alterar/definir o estado do widget.
• Aqui, cada método define a classificação atual do widget por meio de setState
• Conecte o gesto do usuário (tocar na estrela) ao método de mudança de estado adequado.
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 alterará _rating para 3. Como o estado foi alterado, o método de construção será chamado novamente e a interface do usuário será construída e renderizada novamente.
• O código completo do widget RatingBox é o seguinte:
Vamos criar um novo aplicativo e usar nosso recém-criado widget RatingBox para mostrar a classificação do produto.
• Crie um novo aplicativo Flutter no estúdio Android, product_state_app
• Aqui,
• Criamos o widget MyHomePage estendendo o StatelessWidget em vez do StatefulWidget padrãoe, em seguida, removemos o código relevante.
• Inclua nosso recém-criadowidget RatingBox .
• Crie um widget ProductBox para listar o produto junto com a classificação conforme especificado abaixo:
• Atualize o widget MyHomePage para incluir o widget ProductBox conforme especificado abaixo:
• O código completo do aplicativo é o seguinte:
• Por fim, execute o aplicativo e veja os resultados da página Gerenciamento de estado - lista de produtos, conforme mostrado aqui:
Clicando na estrela de classificação atualizará a classificação do produto. Por exemplo, definir a classificação de 2 estrelas para o iPhone exibirá a classificação abaixo:
Estado do aplicativo - scoped_model
O Flutter fornece uma maneira fácil de gerenciar o estado do aplicativo usando o pacote scoped_model. O pacote Flutter é simplesmente uma biblioteca de funcionalidade reutilizável. Aprenderemos sobre os pacotes Flutter em detalhes nos próximos capítulos.
scoped_model fornece três classes principais para habilitar o gerenciamento de estado robusto em um aplicativo que é discutido 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. Ele possui um único método, notifyListeners, que precisa ser chamado sempre que o estado do modelo muda. notifyListeners fará as coisas necessárias para atualizar a IU.
Modelo com Escopo (ScopedModel)
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, precisamos aninhar o ScopedModel.
• Modelo único
• Modelo múltiplo
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 interface do usuário (classificação) do produto.
Descendente do modelo com escopo
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 – builder e child. child é a parte da interface do usuário que não muda e será passada para o construtor. builder aceita uma função com três argumentos:
• content - ScopedModelDescendant passa o contexto da aplicação.
• child - Uma parte da interface do usuário, que não muda com base no modelo.
• model - O modelo real naquela instância.
Vamos alterar nosso exemplo anterior para usar o scoped_model em vez de StatefulWidget
• Crie um novo aplicativo Flutter no estúdio Android, product_scoped_model_app
• Substitua o código de inicialização padrão (main.dart) pelo nosso código product_state_app.
• Copie a pasta assets de product_nav_app para product_rest_app e adicione assets dentro do arquivo pubspec.yaml
• Configure o pacote scoped_model no arquivo pubspec.yaml conforme mostrado abaixo:
Aqui, você deve usar a versão mais recente do pacote http
• O Android Studio alertará que o pubspec.yaml está atualizado.
• Clique na opção Obter dependências. O Android Studio obterá o pacote da Internet e o configurará adequadamente para o aplicativo.
• Substitua o código de inicialização padrão (main.dart) pelo nosso código de inicialização.
• Importar pacote scoped_model no arquivo main.dart
• Vamos criar uma classe Product, Product.dart para organizar as informações do produto.
Aqui, usamos notifyListeners para alterar a IU sempre que a classificação é alterada.
• Vamos escrever um método getProducts na classe Product para gerar nossos registros fictícios de produto.
• Vamos alterar nosso novo widget, RatingBox para suportar o conceito scoped_model.
Aqui, estendemos o RatingBox de StatelessWidget em vez de StatefulWidget. Além disso, usamos o método updateRating do modelo de produto para definir a classificação.
• Vamos modificar nosso widget ProductBox para trabalhar com as classes Product, ScopedModel e ScopedModelDescendant.
Aqui, envolvemos o widget RatingBox em ScopedModel e ScopedModelDecendant.
• Altere o widget MyHomePage para usar nosso widget ProductBox.
Aqui, usamos ListView.builder para criar dinamicamente nossa lista de produtos.
• O código completo do aplicativo é o seguinte:
Por fim, compile e execute o aplicativo para ver o resultado. Funcionará de maneira semelhante ao exemplo anterior, exceto que o aplicativo usa o conceito scoped_model.
Navegação e Roteamento (Navigation and Routing)
Em qualquer aplicativo, navegar de uma página/tela para outra define o fluxo de trabalho do aplicativo. A forma como a navegação de uma aplicação é tratada é chamada de Roteamento. O 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 um aplicativo.
Rota de página de material (MaterialPageRoute)
MaterialPageRoute é um widget usado para renderizar sua interface do usuário, substituindo a tela inteira por uma animação específica da plataforma.
Aqui, o construtor aceitará uma função para construir seu conteúdo fornecendo o contexto atual do aplicativo.
Navigation.push
Navigation.push é usado para navegar para a nova tela usando o widget MaterialPageRoute.
Navigation.pop
Navigation.pop é usado para navegar para a tela anterior.
Vamos criar um novo aplicativo para entender melhor o conceito de navegação.
Crie um novo aplicativo Flutter no estúdio Android, product_nav_app
• Copie a pasta assets de product_nav_app para product_state_app e adicione assets dentro do arquivo pubspec.yaml
• Substitua o código de inicialização padrão (main.dart) pelo nosso código de inicialização.
• Vamos criar uma classe Product para organizar as informações do produto.
• Vamos escrever um método getProducts na classe Product para gerar nossos registros fictícios de produto.
• Vamos incluir nosso novo widget, RatingBox
• Vamos modificar nosso widget ProductBox para funcionar com nossa nova classe Product.
• Vamos reescrever nosso widget MyHomePage para funcionar com o modelo Product e listar todos os produtos usando ListView.
Aqui, usamos MaterialPageRoute para navegar até a página de detalhes do produto.
• Agora, vamos adicionar ProductPage para mostrar os detalhes do produto.
• O código completo do aplicativo é o seguinte:
Execute o aplicativo e clique em qualquer item do produto. Ele mostrará a página de detalhes relevante. 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:
11 Trabalhando com Animação
Animation
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 fornece uma rica interação do usuário. Devido à sua riqueza, a animação torna-se parte integrante dos aplicativos móveis modernos. Flutter framework reconhece a importância da Animação e fornece uma estrutura simples e intuitiva para desenvolver todos os tipos de animações.
Introdução
A animação é um processo de mostrar uma série de imagens/figuras em uma ordem específica dentro de 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 um widget para desaparecer, 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 para a animação. Por exemplo, o fade de um widget será de natureza linear, enquanto o salto de uma bola será de natureza não linear.
• A duração do processo de animação afeta a velocidade (lentidão ou rapidez) da animação.
• A capacidade de controlar o processo de animação, como iniciar a animação, parar a animação, repetir a animação para definir o 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 Baseadas em Classes
O sistema de animação Flutter é baseado em objetos Animation. As principais classes de animação e seu uso são os seguintes:
Animação
Gera valores interpolados entre dois números durante um determinado período. As classes de Animação mais comuns são:
• Animation<double> - interpolar valores entre dois números decimais
• Animation<Color> - interpolar cores entre duas cores
• Animation<Size> - interpolar tamanhos entre dois tamanhos
• AnimationController (Controlador de Animação)- Objeto de animação especial para controlar a própria animação. Ele gera novos valores sempre que o aplicativo está pronto para um novo quadro. Ele suporta animação baseada em 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 (CurvedAnimation)
Semelhante ao AnimationController, mas suporta animação não linear. CurvedAnimation pode ser usado junto com o objeto Animation como abaixo:
Tween<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, o controlador é o controlador de animação real. A curva fornece o tipo de não linearidade e o customTween fornece o intervalo personalizado de 0 a 255.
Fluxo de trabalho da Animação Flutter (Work flow of the FlutterAnimation)
O fluxo de trabalho da animação é o seguinte:
• Definir e iniciar o controlador de animação no initState do StatefulWidget.
• Adicionar ouvinte baseado em animação, addListener para alterar o estado do widget
• 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 de animação durante o processo de construção do widget e aplique-os para largura, altura ou qualquer propriedade relevante em vez do valor original.
Aplicativo de trabalho (Working Application)
Vamos escrever um aplicativo baseado em animação simples para entender o conceito de animação na estrutura do Flutter.
• Crie um novo aplicativo Flutter no estúdio Android, product_animation_app
• Copie a pasta assets de product_nav_app para product_animation_app e adicione assets dentro do arquivo pubspec.yaml
• Remova o código de inicialização padrão (main.dart).
• Adicionar importação e função principal básica
• Crie o widget MyApp derivado de StatefulWidgtet
• Crie o widget _MyAppState e implemente initState e dispose além do método de compilação padrão.
• No método initState, criamos um objeto controlador de animação (controller), um objeto de animação (animation) e iniciamos a animação usando controller.forward.
• No método de dispose, descartamos o objeto controlador de animação (controlador).
• No método build, envie a 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.
• Agora, adicione o widget ProductBox
• Crie um novo widget, MyAnimatedWidget, para fazer uma animação de fade simples 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. Ele aceita um objeto de animação para obter o valor atual da animação. Usamos o valor da animação, animation.value para definir a opacidade do widget filho. Na verdade, o widget animará o widget filho usando o conceito de opacidade.
• Finalmente, crie o widget MyHomePage e use o objeto de animação para animar qualquer conteúdo.
Aqui, usamos FadeAnimation e MyAnimationWidget para animar os dois primeiros itens da lista. FadeAnimation é uma classe de animação incorporada, que usamos para animar seu filho usando o conceito de opacidade.
• O código completo é o seguinte:
• Compile e execute o aplicativo para ver os resultados. A versão inicial e final do aplicativo é a seguinte:
12 Escrevendo Código Específico do Android
O Flutter fornece uma estrutura geral para acessar recursos específicos da plataforma. Isso permite que o desenvolvedor estenda a funcionalidade da estrutura do Flutter usando o código específico da plataforma. A funcionalidade específica da plataforma, como câmera, nível de bateria, navegador etc., pode ser acessada facilmente por meio da estrutura.
A ideia geral de acessar o código específico da plataforma é por meio de protocolo de mensagens simples. O código Flutter, o cliente e o código da plataforma e o host se ligam a um canal de mensagem comum. Cliente envia mensagem para o Host através do Canal de Mensagem. O Host escuta no Canal de Mensagem, recebe a mensagem e faz as funcionalidades necessárias e por fim, retorna o resultado ao Cliente através do Canal de Mensagem.
A arquitetura de código específica da plataforma é mostrada no diagrama de blocos abaixo:
O protocolo de mensagens usa um codec de mensagem padrão (classe StandardMessageCodec) que oferece suporte à serialização binária de valores semelhantes a JSON, como números, strings, booleanos etc. A serialização e a desserialização funcionam de forma transparente entre o cliente e o host.
Vamos escrever um aplicativo simples para abrir um navegador usando o Android SDK e entender como invocar o SDK do aplicativo flutter.
• Crie um novo aplicativo Flutter no estúdio Android, flutter_browser_app
• Substitua o código main.dart pelo código abaixo:
• Aqui, criamos um novo botão para abrir o navegador e definimos seu método onPressed como nulo.
• Agora, importe os seguintes pacotes:
• Aqui, services.dart inclui a funcionalidade para invocar o código específico da plataforma.
• Crie um novo canal de mensagens no widget MyHomePage.
• Escreva um método, _openBrowser para chamar o método específico da plataforma, o método openBrowser por meio do canal de mensagem.
Aqui, usamos platform.invokeMethod para invocar o openBrowser (explicado nas próximas etapas). openBrowser tem um argumento url para abrir um url específico.
• Altere o valor da propriedade onPressed do RaisedButton de null para _openBrowser.
• Abra MainActivity.java (dentro da pasta android) e importe a biblioteca necessária:
• Escreva um método, openBrowser para abrir um navegador
• Agora, defina o nome do canal na classe MainActivity:
• Escreva o código específico do Android para definir o tratamento de mensagens no método onCreate.
Aqui, criamos um canal de mensagem usando a classe MethodChannel e usamos a classe MethodCallHandler para manipular a mensagem. onMethodCall é o método real responsável por chamar o código específico da plataforma correta pela verificação da mensagem. O método onMethodCall extrai a url da mensagem e, em seguida, invoca o openBrowser somente quando a chamada do método é openBrowser. Caso contrário, retorna o método notImplemented.
O código-fonte completo do aplicativo é o seguinte:
main.dart
MainActivity.java
main.dart
Execute o aplicativo e clique no botão Abrir navegador e você verá que o navegador foi iniciado. O aplicativo do navegador - a página inicial é mostrada na captura de tela aqui:
13 Escrevendo código específico do iOS
Writing iOS Specific Code
O acesso ao código específico do iOS é semelhante ao da plataforma Android, exceto pelo uso de linguagens específicas do iOS - Objective-C ou Swift e iOS SDK. Fora isso, 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
• Siga os passos 2 - 6 como no capítulo anterior.
• Inicie o XCode e clique em Arquivo -> Abrir
• Escolha o projeto xcode no diretório ios do nosso projeto flutter.
• Abra AppDelegate.m em Runner -> Runner path. Ele contém o seguinte código:
• Adicionamos um método, openBrowser para abrir o navegador com url especificado. Aceita um único argumento, url.
• No método didFinishLaunchingWithOptions , encontre o controlador e defina-o na variável do controlador.
• No método didFinishLaunchingWithOptions, defina o canal do navegador como flutterapp.tutorialspoint.com/browse:
• Crie uma variável, weakSelf e defina a classe atual:
• Agora, implemente setMethodCallHandler. Chame openBrowser combinando call.method.
Obtenha url invocando call.arguments e passe-o enquanto chama openBrowser.
• O código completo é o seguinte:
• Configuração de projeto aberto.
• Vá para Capacidades e ative os Modos de segundo plano
• Adicionar *busca de plano de fundo e notificação remota**
• Agora, execute o aplicativo. Funciona de maneira semelhante à versão do Android, mas o navegador Safari será aberto em vez do Chrome.
14 Introdução ao Pacote
Introduction to Package
A maneira do Dart de organizar e compartilhar um conjunto de funcionalidades é por meio de Package . Dart Package é simplesmente bibliotecas ou módulos compartilháveis. Em geral, o pacote Dart é o mesmo do aplicativo Dart, exceto que o pacote Dart não possui ponto de entrada do aplicativo, principal.
A estrutura geral do Package (considere um pacote de demonstração, my_demo_package) é a seguinte:
• lib/src/*: arquivos de código Dart privados.
• lib/my_demo_package.dart: arquivo de código Dart principal . Ele pode ser importado para um aplicativo como:
• 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:
• lib/* : qualquer número de arquivos de código Dart organizados em qualquer estrutura de pasta personalizada. O código pode ser acessado como,
• pubspec.yaml: Especificação do projeto, igual à da aplicação.
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 funcionalidade semelhante, eles podem ser categorizados com base em sua funcionalidade.
Pacote Dart (Dart Package)
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 básicas de utilidade como substantivos (listar substantivos em inglês), sílabas (especificar o número de sílabas em uma palavra.
Pacote Flutter (Flutter Package)
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 do framework Flutter.
Plug-in Flutter
Código Dart genérico, que depende da estrutura do Flutter, bem como do código da plataforma subjacente (Android SDK ou iOS SDK). Por exemplo, a câmera é um plug-in para interagir com a câmera do dispositivo. Depende da estrutura do Flutter, bem como da estrutura subjacente, para obter acesso à câmera.
Usando um pacote Dart
Os pacotes do Dart são hospedados e publicados no servidor ativo, https://pub.dartlang.org . Além disso, o Flutter fornece uma ferramenta simples para gerenciar pacotes Dart no aplicativo. As etapas necessárias para usar como Package são as seguintes:
• Inclua o nome do pacote e a versão necessária no pubspec.yaml conforme mostrado abaixo:
• O número da versão mais recente pode ser encontrado verificando o servidor online.
• Instale o pacote no aplicativo usando o seguinte comando:
• Ao desenvolver 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 do Dart podem ser instalados ou atualizados no Android Studio usando as opções do menu.
• Importe o arquivo necessário usando o comando mostrado abaixo e comece a trabalhar:
• Use qualquer método disponível no pacote,
• Aqui, usamos a função de substantivos para obter e imprimir as 50 palavras principais.
Desenvolvendo um pacote de plug-in do Flutter
O desenvolvimento de um plug-in Flutter é semelhante ao desenvolvimento de um aplicativo Dart ou pacote Dart. A única exceção é que o plug-in usará a API do sistema (Android ou iOS) para obter a funcionalidade específica da plataforma necessária.
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
A funcionalidade do plug-in my_browser é permitir que o aplicativo abra o site fornecido no navegador específico da plataforma.
• Inicie o Android Studio
• Clique em Arquivo -> Novo projeto do Flutter e selecione a opção Flutter Plugin.
• Você pode ver uma janela de seleção de plug-in do Flutter, conforme mostrado aqui:
• Insira my_browser como nome do projeto e clique em Avançar.
• Insira o nome do plug-in e outros detalhes na janela conforme mostrado aqui:
• Digite 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.
• Abra o arquivo my_browser.dart e escreva um método, openBrowser, para invocar o método openBrowser específico da plataforma.
• Abra o arquivo MyBrowserPlugin.java e importe as seguintes classes:
• Aqui, temos que importar a biblioteca necessária para abrir um navegador do Android.
• Adicionada nova variável privada mRegistrar do tipo Registrar na classe MyBrowserPlugin.
• Aqui, Registrar é usado para obter informações de contexto do código de chamada.
• Adicione um construtor para definir Registrar na classe MyBrowserPlugin.
• Altere registerWith para incluir nosso novo construtor na classe MyBrowserPlugin.
• Altere onMethodCall para incluir o método openBrowser na classe MyBrowserPlugin.
• Escreva o método openBrowser específico da plataforma para acessar o navegador na classe MyBrowserPlugin:
• O código-fonte completo do plug-in my_browser é o seguinte:
meu_browser.dart
MyBrowserPlugin.java
• Crie um novo projeto, my_browser_plugin_test para testar nosso plug-in recém-criado.
• Abra pubspec.yaml e defina my_browser como uma dependência de plug-in:
• O Android studio alertará que o pubspec.yaml está 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.
• Abra main.dart e inclua o plugin my_browser conforme abaixo:
• Chame a função openBrowser do plug-in my_browser conforme mostrado abaixo:
• O código completo do main.dart é o seguinte:
• Execute o aplicativo, clique no botão Abrir navegador e veja se o navegador é iniciado. Você pode ver um aplicativo do navegador - página inicial, conforme mostrado na captura de tela abaixo:
• Você pode ver um aplicativo do navegador - tela do navegador, conforme mostrado na captura de tela abaixo:
15 Acessando a API REST
Flutter fornece pacote http para consumir recursos HTTP. http é uma biblioteca baseada em Future e usa os recursos await e async. 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 um URL e informações adicionais por meio do Dart Map (dados de postagem, cabeçalhos adicionais, etc.). Ele solicita o servidor e coleta a resposta de volta no padrão async/await. Por exemplo, o código abaixo lê os dados do url especificado e os imprime no console.
Alguns dos métodos principais são os seguintes:
• read - Solicita o URL especificado por meio do método GET e retorna a resposta como Future<String>
• get - Solicita o url especificado por meio do método GET e retorna a resposta como Future<Response>. Response é uma classe que contém as informações de resposta.
• post - Solicita o URL especificado por meio do método POST postando os dados fornecidos e retorna a resposta como Future<Response>
• put - Solicita o url especificado por meio do método PUT e retorna a resposta como Future<Response>
• head - Solicita a url especificada por meio do método HEAD e retorna a resposta como Future<Response>
• delete - Solicita o url especificado por meio do método DELETE e retorna 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 muitos pedidos forem feitos 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:
Acessando a API de serviço do produto
Vamos criar um aplicativo simples para obter dados de produtos de um servidor da Web e, em seguida, mostrar os produtos usando ListView .
• Crie um novo aplicativo Flutter no estúdio Android, product_rest_app
• Substitua o código de inicialização padrão (main.dart) pelo nosso código product_nav_app .
• Copie a pasta assets de product_nav_app para product_rest_app e adicione assets dentro do arquivo pubspec.yaml
• Configure o pacote http no arquivo pubspec.yaml conforme mostrado abaixo:
• Aqui, usaremos a versão mais recente do pacote http. O Android Studio enviará um alerta de pacote informando que o 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.
• Importe o pacote http no arquivo main.dart:
• Crie um novo arquivo JSON, products.json com as informações do produto conforme mostrado abaixo:
• Crie uma nova pasta, JSONWebServer e coloque o arquivo JSON, products.json.
• Execute qualquer servidor web com JSONWebServer como seu 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 o aplicativo de servidor http baseado em nó. Siga as etapas abaixo para instalar e executar o aplicativo do servidor http.
• Instale o aplicativo Nodejs (https://nodejs.org/en/)
• Vá para a pasta JSONWebServer.
• Instale o pacote http-server usando npm
• Agora, execute 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 os dados mapeados Map no objeto Product. Normalmente, o arquivo JSON será convertido em objeto Dart Map e, em seguida, convertido em objeto relevante (Produto)
• O código completo do Product.dart é o seguinte:
• 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>.
• Observe os seguintes pontos aqui:
• Future é usado para carregar lentamente as informações do produto. Lazy loading é um conceito para adiar a execução do código até que seja necessário.
• http.get é usado para buscar os dados da Internet.
• 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 incluí-lo no construtor. Além disso, remova a variável items e seu método relevante, a chamada do método getProducts. Colocando a variável de produtos no construtor. Isso permitirá buscar os produtos da Internet apenas uma vez quando o aplicativo for iniciado pela primeira vez.
• Altere a opção inicial (MyHomePage) no método de construção do widget MyApp para acomodar as alterações acima:
• Altere a função principal para incluir argumentos Future<Product>:
• Crie um novo widget, ProductBoxList para criar a lista de produtos na página inicial.
Observe que usamos o mesmo conceito usado no aplicativo de navegação para listar o produto, exceto que ele é projetado como um widget separado, passando produtos (objeto) do tipo List<Product>.
• Finalmente, 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.
• Observe aqui que usamos o widget FutureBuilder para renderizar o widget. O FutureBuilder 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.
• O código completo do main.dart é o seguinte:
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 locais e estáticos inseridos durante a codificação do aplicativo.
16 Conceitos de Banco de Dados
Database Concepts
O Flutter fornece muitos pacotes avançados para trabalhar com bancos de dados. Os pacotes mais importantes são:
• sqflite – Usado para acessar e manipular banco de dados SQLite, e
• firebase_database – Usado para acessar e manipular o banco de dados NoSQL hospedado na nuvem do Google.
Neste capítulo, vamos discutir cada um deles em detalhes.
SQLite
O banco de dados SQLite é o mecanismo de banco de dados embutido baseado em SQL de fato e padrão. É 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 sqlite é a seguinte:
• Criar/abrir (método openDatabase) um banco de dados SQLite.
• Execute a instrução SQL (método de execução) no banco de dados SQLite.
• Métodos de consulta avançados (método de consulta) para reduzir ao 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 do 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.
• Crie um novo aplicativo Flutter no estúdio Android, product_sqlite_app
• Substitua o código de inicialização padrão (main.dart) pelo nosso código product_rest_app .
• Copie a pasta assets de product_nav_app para product_rest_app e adicione assets dentro do arquivo *pubspec.yaml`
• Configure o pacote sqflite no arquivo pubspec.yaml conforme mostrado abaixo:
Use o número da versão mais recente do sqflite no lugar de qualquer
• Configure o pacote path_provider no arquivo pubspec.yaml conforme mostrado abaixo:
• 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 arquivo .
• O Android Studio alertará que o pubspec.yaml está atualizado.
• 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 as propriedades do produto como nome, preço, etc. Então, adicione a propriedade id na classe Product. Além disso, adicione um novo método, toMap para converter objeto de produto em objeto de mapa. fromMap e toMap são usados para serializar e desserializar o objeto Product e é usado em métodos de manipulação de banco de dados.
• Crie um novo arquivo, Database.dart na pasta lib para gravar a funcionalidade relacionada ao SQLite .
• Importe a instrução de importação necessária em Database.dart
• Observe os seguintes pontos aqui:
• async é usado para escrever métodos assíncronos.
• io é usado para acessar arquivos e diretórios.
• path é usado para acessar a função do utilitário dart core relacionada a caminhos de arquivo.
• path_provider é usado para obter o caminho temporário e do aplicativo.
• sqflite é usado para manipular o banco de dados SQLite.
• Crie uma nova classe SQLiteDbProvider
• Declare um objeto SQLiteDbProvider estático baseado em singleton conforme especificado abaixo:
• O objeto SQLiteDBProvoider e seu método podem ser acessados através da variável static db.
• 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.
• Aqui, usamos os seguintes métodos:
• getApplicationDocumentsDirectory - Retorna o caminho do diretório do aplicativo
• join - Usado para criar um caminho específico do sistema. Nós o usamos para criar o caminho do banco de dados.
• openDatabase - Usado para abrir um banco de dados SQLite
• onOpen - Usado para escrever código ao abrir um banco de dados
• 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 (?), ela aceitará valores como lista no segundo argumento.
• Escreva um método para obter todos os produtos no banco de dados:
• Aqui, fizemos o seguinte:
• Método de consulta usado para buscar todas as informações do produto. query fornece um atalho para consultar informações de uma tabela sem escrever toda a consulta. query método irá gerar a própria consulta adequada usando nossa entrada como colunas, orderBy, etc.,
• Usou o método fromMap de Product para obter detalhes do produto fazendo um loop no objeto de resultados, que contém todas as linhas da tabela.
• Escreva um método para obter um produto específico para id
• Aqui, usamos where e whereArgs para aplicar filtros.
• Crie três métodos - inserir, atualizar e excluir método para inserir, atualizar e excluir produtos do banco de dados
• O código final do Database.dart é o seguinte:
• Altere o método principal para obter as informações do produto.
• 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 do 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.
O Flutter fornece um pacote especial, cloud_firestore, para programar com o Cloud Firestore. Vamos criar uma loja online de produtos no Cloud Firestore e criar um aplicativo para acessar a loja de produtos.
• Crie um novo aplicativo Flutter no estúdio Android, product_firebase_app
• Substitua o código de inicialização padrão (main.dart) pelo nosso código product_rest_app .
• Copie o arquivo Product.dart de product_rest_app para a pasta lib.
• Copie a pasta assets de product_rest_app para product_firebase_app e adicione assets dentro do arquivo pubspec.yaml
• Configure o pacote cloud_firestore no arquivo pubspec.yaml conforme mostrado abaixo:
• Aqui, use a versão mais recente do pacote cloud_firestore.
• O Android studio irá alertar que o pubspec.yaml está 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.
• Crie um projeto no Firebase usando as seguintes etapas:
• Crie uma conta do Firebase selecionando um Plano gratuito em https://firebase.google.com/pricing/
• Assim 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.
• Clique em Adicionar projeto e abrirá uma página de criação de projeto.
• Digite products app db como nome do projeto e clique na opção Criar projeto.
• Acesse *Console do Firebase.
• Clique em Visão geral do projeto. Ele abre a página de visão geral do projeto.
• Clique no ícone do Android. Ele abrirá a configuração do projeto específica para o desenvolvimento do Android.
• Insira o nome do pacote Android, com.tutorialspoint.flutterapp.product_firebase_app
• Clique em Registrar aplicativo. Ele gera um arquivo de configuração do projeto, google_service.json
•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.
• Abra android/app/build.gradle e inclua o seguinte código:
• Abra android/build.gradle e inclua a seguinte configuração:
Aqui, o plug-in e o caminho da classe são usados para ler o arquivo google_service.json.
• Abra android/app/build.gradle e inclua o seguinte código também.
Essa dependência permite que o aplicativo Android use várias funcionalidades de dex.
• Siga as etapas restantes no Firebase Console ou simplesmente ignore-as.
• Crie uma loja de produtos no projeto recém-criado usando as seguintes etapas:
• Acesse o console do Firebase.
• Abra o projeto recém-criado.
• Clique na opção Banco de dados no menu à esquerda.
• Clique na opção Criar banco de dados.
• Clique em Iniciar no modo de teste e depois em Ativar
• Clique em Adicionar coleção. Digite product como nome da coleção e clique em Next.
• Digite as informações do produto de amostra conforme mostrado na imagem aqui:
• Adicionar informações adicionais sobre o produto usando as opções Adicionar documento .
• Abra o arquivo main.dart, importe o arquivo de plug-in do Cloud Firestore e remova o pacote http.
• Remova parseProducts e atualize fetchProducts para buscar produtos do Cloud Firestore em vez da API de serviço do produto
• Aqui, o método Firestore.instance.collection é usado para acessar a coleção de produtos disponível no armazenamento em nuvem. Firestore.instance.collection fornece muitas opções para filtrar a coleção para obter os documentos necessários. Porém, não aplicamos nenhum filtro para obter todas as informações do produto.
• O Cloud Firestore fornece a coleção por meio do conceito Dart Stream e, portanto, modifica o tipo de produto no widget MyApp e MyHomePage de Future<list<Product>> para Stream<QuerySnapshot>.
• Altere o método de construção do widget MyHomePage para usar StreamBuilder em vez de FutureBuilder.
• Aqui, buscamos as informações do produto como tipo List<DocumentSnapshot>. Como nosso widget, ProductBoxList não é compatível com documentos, convertemos os documentos no tipo List<Product> e o usamos ainda mais.
• 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.
17 Internacionalização
Internationalization
Atualmente, os aplicativos móveis são usados por clientes de diferentes países e, como resultado, os aplicativos são necessários para exibir o conteúdo em diferentes idiomas. Habilitar um aplicativo para funcionar em vários idiomas é chamado de Internacionalização do aplicativo.
Para que um aplicativo funcione em diferentes idiomas, ele deve primeiro encontrar a localidade atual do sistema em que 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 do Flutter fornece três classes básicas para localização e extensas classes de utilitários derivadas de classes básicas para localizar um aplicativo.
As classes básicas são as seguintes:
• 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:
Aqui, o primeiro argumento é o código do idioma e o segundo argumento é o código do país.
Outro exemplo de criação de localidade em espanhol da Argentina (es-ar) é o seguinte:
• Localizações - Localizações é um widget genérico usado para definir a localidade e os recursos localizados de seu filho.
• Aqui, CustomLocalizations é uma nova classe personalizada criada especificamente para obter determinado conteúdo localizado (título e mensagem) para o widget. of 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 Localizações é carregado. Ele tem três métodos substituíveis:
• isSupported - Aceita uma localidade e retorna se a localidade especificada é suportada ou não.
Aqui, o delegado funciona apenas para as localidades en e es.
• load - Aceita uma localidade e começa a carregar os recursos para a localidade especificada.
Aqui, o método load retorna CustomLocalizations. O retorno CustomLocalizations pode ser usado para obter valores de título e mensagem em inglês e espanhol.
• shouldReload - Especifica se o recarregamento de CustomLocalizations é necessário quando seu widget Localizations é reconstruído.
• O código completo de CustomLocalizationDelegate é o seguinte:
Em geral, os aplicativos Flutter são baseados em dois widgets de nível raiz, MaterialApp ou WidgetsApp. O 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 WidgetsLocaliations e eles são GlobalMaterialLocalizations.delegate e GlobalWidgetsLocalizations.delegate, respectivamente.
Vamos criar um aplicativo habilitado para internacionalização simples para testar e entender o conceito.
• Crie um novo aplicativo flutter, flutter_localization_app
• O Flutter suporta a internacionalização usando o pacote flutter exclusivo, flutter_localizations. A ideia é separar o conteúdo localizado do SDK principal. Abra o pubspec.yaml e adicione o código abaixo para habilitar o pacote de internacionalização:
• O Android Studio exibirá o seguinte alerta de que o pubspec.yaml está atualizado.
• Clique na opção Obter dependências. O Android Studio obterá o pacote da Internet e o configurará adequadamente para o aplicativo.
• Importe o pacote flutter_localizations no main.dart da seguinte forma:
• Aqui, o objetivo do SynchronousFuture é carregar as localizações personalizadas de forma síncrona.
• Crie localizações personalizadas e seu delegado correspondente conforme especificado abaixo:
• Aqui, CustomLocalizations é criado para oferecer suporte à localização de título e mensagem no aplicativo e CustomLocalizationsDelegate é usado para carregar CustomLocalizations.
• Adicione delegados para MaterialApp, WidgetsApp e CustomLocalization usando as propriedades MaterialApp, localizationsDelegates e supportedLocales conforme especificado abaixo:
• Use o método CustomLocalizations para obter o valor localizado do título e da mensagem e use-o no local apropriado conforme especificado abaixo:
• Aqui, modificamos a classe MyHomePage de StatefulWidget para StatelessWidget por motivos de simplicidade e usamos CustomLocalizations para obter o título e a mensagem.
• Compile e execute o aplicativo. O aplicativo mostrará seu conteúdo em inglês.
• Feche o aplicativo. Vá para Configurações -> Sistema -> Idiomas e entrada -> Idiomas *
• 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 para cima de inglês. Isso definirá o espanhol como primeira língua e tudo será alterado para o texto em espanhol.
• Agora reinicie o aplicativo de internacionalização e você verá o título e a mensagem em espanhol.
• Podemos reverter o idioma para inglês movendo a opção Inglês acima da opção Espanhol na configuração.
• O resultado da aplicação (em espanhol) é mostrado na captura de tela abaixo:
Usando o pacote intl
O Flutter fornece um pacote intl para simplificar ainda mais o desenvolvimento de aplicativos móveis localizados. O pacote intl fornece métodos e ferramentas especiais para gerar mensagens específicas de idioma de forma semi-automática.
Vamos criar um novo aplicativo localizado usando o pacote intl e entender o conceito.
• Crie um novo aplicativo flutter, flutter_intl_app
• Abra pubspec.yaml e adicione os detalhes do pacote.
• O Android studio exibirá o alerta conforme mostrado abaixo informando que o pubspec.yaml está atualizado.
• Clique na opção Obter dependências. O Android Studio obterá o pacote da Internet e o configurará adequadamente para o aplicativo.
• Copie o main.dart do exemplo anterior, flutter_internationalization_app
• Importe o intl pacakge conforme mostrado abaixo:
• Atualize a classe CustomLocalization conforme mostrado no código abaixo:
• Aqui, usamos três métodos do pacote intl em vez de métodos personalizados. Caso contrário, os conceitos são os mesmos.
• Intl.canonicalizedLocale - Usado para obter o nome de localidade correto.
• Intl.defaultLocale - Usado para definir o local atual.
• Intl.message - Usado para definir novas mensagens.
• importar o arquivo l10n/messages_all.dart . Iremos gerar este arquivo em breve.
• Agora, crie uma pasta, lib/l10n
• Abra um prompt de comando e vá para o diretório raiz do aplicativo (onde pubspec.yaml está disponível) e execute o seguinte comando:
• Aqui, o comando irá gerar, arquivo intl_message.arb, um modelo para criar mensagem em localidade diferente. O conteúdo do arquivo é o seguinte:
• Copie intl_message.arb e crie um novo arquivo, intl_en.arb
• Copie intl_message.arb e crie um novo arquivo, intl_es.arb e altere o conteúdo para o idioma espanhol conforme mostrado abaixo:
• Agora, execute o seguinte comando para criar o arquivo de mensagem final, messages_all.dart
• Compile e execute o aplicativo. Funcionará de maneira semelhante ao aplicativo acima, flutter_localization_app.
18 Testando
Testing
O teste é uma fase muito importante no ciclo de vida de desenvolvimento de um aplicativo. Ele 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 um método de uma classe. Mas, não reflete o ambiente real e, consequentemente, é a menor opção para encontrar os bugs.
Teste de widget: O teste de widget é baseado em garantir a exatidão da criação do widget, renderização e interação com outros widgets conforme o 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 tanto o teste de unidade quanto o teste de widget junto com o componente externo 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.
O Flutter fornece suporte para todos os tipos de teste. Ele fornece suporte extensivo e exclusivo para testes de widgets. Neste capítulo, discutiremos o teste de widget em detalhes.
Teste de widget
A estrutura de teste Flutter fornece o método testWidgets para testar widgets.
Aceita dois argumentos:
• Descrição do teste
• Código de teste
Etapas Envolvidas
O teste de widget envolve três etapas distintas:
• Renderize o widget no ambiente de teste.
• WidgetTester é a classe fornecida pela estrutura de teste do Flutter para construir e renderizar o widget. O método pumpWidget da classe WidgetTester aceita qualquer widget e o renderiza no ambiente de teste.
• Encontrar o widget, que precisamos testar.
• A estrutura do Flutter fornece 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 localiza o widget que contém o texto especificado.
• find.byKey encontra o widget por sua chave específica.
• find.byWidget encontra o widget por sua variável de instância
• Garantir que o widget funcione conforme o esperado.
• Flutter framework fornece muitas opções para combinar o widget com o widget esperado e eles são normalmente chamados de Matchers . Podemos usar o método expect fornecido pela estrutura de teste para corresponder ao widget, que encontramos na segunda etapa com nosso widget esperado, escolhendo qualquer um dos correspondentes. Alguns dos matchers importantes são os seguintes:
• findOneWidget - verifica se um único widget foi encontrado.
• findNothing - verifica se nenhum widget foi encontrado.
• findWidgets - verifica se mais de um único widget foi encontrado.
• findNWidgets - verifica se um número N de widgets foi encontrado.
O código de teste completo é o seguinte:
Aqui, renderizamos um widget MaterialApp com o texto Hello usando o widget Text em seu corpo. Em seguida, usamos find.text para localizar o widget e, em seguida, combinamos usando findOneWidget.
Exemplo de trabalho
Vamos criar um aplicativo de vibração simples e escrever um teste de widget para entender melhor as etapas envolvidas e o conceito.
• Crie um novo aplicativo flutter, flutter_test_app no estúdio Android.
• Abra widget_test.dart na pasta de teste. Ele tem um código de teste de amostra conforme abaixo:
• Aqui, o código de teste faz as seguintes funcionalidades:
• Renderiza o widget MyApp usando tester.pumpWidget
• Garante que o contador seja inicialmente zero usando os correspondentes findOneWidget e findNothing.
• Localiza o botão de incremento do contador usando o método find.byIcon.
• Toca no botão de incremento do contador usando o método tester.tap.
• Garante que o contador seja aumentado usando os correspondentes findOneWidget e findNothing.
• Vamos tocar novamente no botão de incremento do contador e, em seguida, verificar se o contador aumentou para dois.
• Clique no menu Executar.
• Clique em testes na opção widget_test.dart. Isso executará o teste e relatará o resultado na janela de resultados.
19 Implantação
Deployment
Este capítulo explica como implantar o aplicativo Flutter nas plataformas Android e iOS.
Aplicativo para Android
• Altere o nome do aplicativo usando a entrada android:label no arquivo de manifesto do Android. O 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.
• Altere o ícone do iniciador usando a entrada android:icon no arquivo de manifesto.
• Assine o aplicativo usando a opção padrão conforme necessário
• Habilite Proguard e Ofuscação usando a opção padrão, se necessário.
• Crie um arquivo APK de lançamento executando o comando abaixo:
• Você pode ver uma saída conforme mostrado abaixo:
• Instale o APK em um dispositivo usando o seguinte comando:
• 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.
• Atualize o Bundle Identifier na configuração do projeto XCode para definir o ID do pacote, que usamos na etapa 1.
• Assine o código conforme necessário usando o método padrão.
• Adicione um novo ícone de aplicativo conforme necessário usando o método padrão.
• Gere o arquivo IPA usando o seguinte comando:
• Agora, você pode ver a seguinte saída:
• Teste o aplicativo enviando o aplicativo, o arquivo IPA para o TestFlight usando o método padrão.
• Finalmente, envie o aplicativo para a App Store usando o método padrão.
20 Ferramentas de Desenvolvimento
Development Tools
Este capítulo explica detalhadamente sobre 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 do Flutter com diferentes ferramentas de desenvolvimento.
Conjuntos de widgets
O Google atualizou os conjuntos de widgets Material e Cupertino para fornecer qualidade perfeita de pixel no design dos componentes. A próxima versão do flutter 1.2 será projetada para oferecer suporte a eventos de teclado de desktop e suporte ao mouse hover.
Desenvolvimento Flutter com Visual Studio Code
O Visual Studio Code oferece suporte ao desenvolvimento flutter e fornece atalhos extensos para um desenvolvimento rápido e eficiente. Alguns dos principais recursos fornecidos pelo Visual Studio Code para desenvolvimento flutter estão listados abaixo:
• Assistente de código - Quando quiser verificar as opções, você pode usar Ctrl+Espaço para obter uma lista de opções de autocompletar código.
• Correção rápida - Ctrl+. é uma ferramenta de correção rápida para ajudar na correção do código.
• Atalhos durante a codificação
• Fornece documentação detalhada nos comentários.
• 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 tem trabalhado em outra ferramenta de desenvolvimento chamada Dart DevTools. É um conjunto de programação baseado na web. Ele suporta as plataformas Android e iOS. Ele é baseado na visualização da linha do tempo para que os desenvolvedores possam analisar facilmente seus aplicativos.
Instalar DevTools
Para instalar o DevTools execute o seguinte comando em seu console:
Agora você pode ver a seguinte saída:
Executar servidor
Você pode executar o servidor DevTools usando o seguinte comando:
Agora, você receberá uma resposta semelhante a esta,
Inicie sua inscrição
Vá para o seu aplicativo, abra o simulador e execute usando o seguinte comando:
Agora, você está conectado ao DevTools.
Inicie o DevTools no navegador
Agora acesse a url abaixo no navegador, para iniciar o DevTools:
Você receberá uma resposta como mostrado abaixo:
Flutter SDK
Para atualizar o Flutter SDK, use o seguinte comando:
Você pode ver uma saída como mostrado abaixo:
Para atualizar os pacotes do Flutter, use o seguinte comando:
Você pode ver a seguinte resposta,
Inspetor Flutter
Ele é usado para explorar árvores de widgets flutuantes. Para conseguir isso, execute o comando abaixo em seu console,
Você pode ver uma saída como mostrado abaixo:
Agora vá para o url, http://127.0.0.1:50399/ você pode ver o seguinte resultado:
21 Escrevendo Aplicações Avançadas
Writing Advanced Applications
Neste capítulo, aprenderemos como escrever um aplicativo móvel completo, a calculadora_de_despesas. O propósito da calculadora_de_despesas é armazenar nossas informações de despesas. O recurso completo do aplicativo é o seguinte:
• Lista de despesas
• Formulário para inserir novas despesas
• Opção para editar/excluir as despesas existentes
• Total de despesas em qualquer instância.
Vamos programar o aplicativo de calculadora de despesas usando os recursos avançados mencionados abaixo da estrutura do Flutter.
• Uso avançado de ListView para mostrar a lista de despesas
• Programação de formulários
• Programação de banco de dados SQLite para armazenar nossas despesas
• gerenciamento de estado scoped_model para simplificar nossa programação.
Vamos começar a programar o aplicativo de calculadora de despesas .
• Crie um novo aplicativo Flutter, Expense_calculator no Android Studio.
• Abra pubspec.yaml e adicione dependências de pacote.
• Observe estes pontos aqui:
• sqflite é usado para programação de banco de dados SQLite.
• path_provider é usado para obter o caminho do aplicativo específico do sistema.
• scoped_model é usado para gerenciamento de estado.
• intl é usado para formatação de data
• O Android Studio exibirá o seguinte alerta de que o pubspec.yaml está atualizado.
• Clique na opção Obter dependências. O Android Studio obterá o pacote da Internet e o configurará adequadamente para o aplicativo.
• Remova o código existente em main.dart
• Adicionar novo arquivo, Expense.dart para criar a classe Expense. A classe de despesas terá as propriedades e métodos abaixo.
• propriedade: id - ID exclusivo para representar uma entrada de despesa no banco de dados SQLite.
• propriedade: valor - Valor gasto.
• propriedade: data - Data em que o valor é gasto.
• propriedade: categoria - A categoria representa a área em que o valor é gasto. por exemplo, comida, viagens, etc.,
• formattedDate - Usado para formatar a propriedade de data
• fromMap - Usado para mapear o campo da tabela do banco de dados para a propriedade no objeto de despesa e para criar um novo objeto de despes.
• toMap - Usado para converter o objeto de despesa em Dart Map, que pode ser usado posteriormente na programação do banco de dados
• colunas - Variável estática usada para representar o campo do banco de dados.
• Insira e salve o seguinte código no arquivo Expense.dart.
• O código acima é simples e auto-explicativo.
• Adicione um 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. Ele será usado para listar todas as informações de despesas do usuário.
• 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 as informações de despesas específicas para o usuário.
• Obtenha o total de despesas do usuário usando o método getTotalExpense. Ele será usado para mostrar a despesa total atual para o usuário.
• Adicionar novas informações de despesas ao banco de dados usando o método de inserção. Ele 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á usado para editar e atualizar a entrada de despesas existente disponível no sistema pelo usuário.
• Excluir informações de despesas existentes usando o método de exclusão. Será utilizado remover o lançamento de despesa existente disponível no sistema pelo usuário.
O código completo da classe SQLiteDbProvider é o seguinte:
• Aqui,
• database é a propriedade para obter o objeto SQLiteDbProvider.
• initDB é um método usado para selecionar e abrir o banco de dados SQLite.
• Crie um novo arquivo, ExpenseListModel.dart para criar ExpenseListModel. O objetivo do modelo é manter as informações completas das despesas do usuário na memória e atualizar a interface do usuário do aplicativo sempre que as despesas do usuário mudarem na memória. É baseado na classe Model do pacote scoped_model. Possui as seguintes propriedades e métodos:
• _items - lista privada de despesas
• items - getter para _items como UnmodifiableListView<Expense> para evitar alterações inesperadas ou acidentais na lista.
• totalExpense - getter para despesas totais com base na variável itens.
• load - Usado para carregar as despesas completas do banco de dados e na variável _items. Ele também chama notifyListeners para atualizar a IU.
• byId - Usado para obter uma determinada despesa da variável _items.
• 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.
• 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.
• 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.
O código completo da classe ExpenseListModel é o seguinte:
• Abra o arquivo main.dart. Importe as classes conforme especificado abaixo:
• Adicione a função principal e chame runApp passando o widget ScopedModel<ExpenseListModel>.
• Aqui,
• O objeto despesas carrega todas as informações de despesas do usuário do banco de dados. Além disso, quando o aplicativo for aberto pela primeira vez, ele criará o banco de dados necessário com as tabelas adequadas.
• ScopedModel fornece as informações de despesas durante todo o ciclo de vida do aplicativo e garante a manutenção do estado do aplicativo em qualquer instância. Ele nos permite usar StatelessWidget em vez de StatefulWidget.
• Crie um MyApp simples usando o widget MaterialApp.
• 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.
• Aqui,
• ScopedModelDescendant é usado para passar o modelo de despesa para o widget ListView e FloatingActionButton.
• Os widgets ListView.separated e ListTile são usados para listar as informações de despesas.
• O widget descartável é usado para excluir a entrada de despesas usando o gesto de furto.
• O navegador é usado para abrir a interface de edição de uma entrada de despesas. Ele pode ser ativado tocando em uma entrada de despesa.
• Crie um widget FormPage. A finalidade do widget FormPage é adicionar ou atualizar uma entrada de despesa. Ele também lida com a validação de entradas de despesas.
• Aqui,
• TextFormField é usado para criar entrada de formulário.
• A propriedade validator de TextFormField é usada para validar o elemento de formulário junto com os padrões RegEx.
• A função _submit é usada junto com o objeto de despesas para adicionar ou atualizar as despesas no banco de dados.
• O código completo do arquivo main.dart é o seguinte:
• Agora, execute o aplicativo.
• Adicione novas despesas usando o botão flutuante.
• Edite as despesas existentes tocando na entrada de despesas
• Exclua as despesas existentes deslizando a entrada de despesas em qualquer direção.
Algumas das capturas de tela do aplicativo são as seguintes:
22 Conclusão
Conclusion
A estrutura do Flutter faz um ótimo trabalho ao fornecer uma excelente estrutura para criar aplicativos móveis de uma maneira verdadeiramente independente da plataforma. Ao fornecer simplicidade no processo de desenvolvimento, alto desempenho no aplicativo móvel resultante, interface de usuário rica e relevante para a plataforma Android e iOS, a estrutura do Flutter certamente permitirá que muitos novos desenvolvedores desenvolvam aplicativos móveis de alto desempenho e cheios de recursos no futuro próximo.