Alura > Cursos de Mobile > Cursos de Flutter > Conteúdos de Flutter > Primeiras aulas do curso Flutter com WebAPI: integrando sua aplicação

Flutter com WebAPI: integrando sua aplicação

Entendendo o Projeto base e API REST - Apresentação

Olá! Boas-vindas ao curso de Flutter com Web API: Integrando sua aplicação. Meu nome é Ricarth Lima e eu serei seu instrutor nessa jornada.

Por uma questão de acessibilidade, vou me autodescrever: sou um homem de pele clara e tenho cabelos bem cacheados, quase crespos, olhos castanhos, um nariz grande e uma boca larga. Eu uso óculos de armação retangular escura e tenho uma barba medianamente espessa. Durante a maioria do curso, usarei uma camisa azul escura.

Agora vamos falar de algo importante que vocês precisam saber antes de começarem este curso, ou seja, dos pré-requisitos. É essencial que tenham uma boa base de Dart para fazerem esse curso, então recomendo fortemente que concluam a Formação de Dart.

Outro requisito muito importante é o curso Flutter: persistência interna. Também é importante terem assistido o Alura+ Flutter: como usar navegação nomeada, porque esse conhecimento será muito usado neste curso.

Ao final deste curso, produziremos um simples aplicativo de diário, inclusive o nome é justamente Diário Simples. Nele, a pessoa poderá registrar os progressos de cada dia, como foi o dia e assim por diante. Vamos conferir o protótipo.

Tela do aplicativo "Diário Simples". Há uma App Bar preta na parte superior da tela. No canto direito da App Bar está escrito "8 | 8 | 2022" em fonte branca. Já no canto esquerdo, há uma seta branca em formato de círculo. Abaixo da App Bar há um retângulo quase da largura da tela e altura de aproximadamente ⅕ da tela. O retângulo está contornado por uma borda fina preta. Ocupando o canto superior esquerdo do retângulo há um quadrado cinza, cuja altura e largura é um pouco maior que metade da altura do retângulo. No centro do quadrado está escrito "1" em fonte branca. Abaixo do quadrado há um retângulo branco com "seg" escrito no centro. Ao lado direito, há uma frase em inglês. A frase está centralizada em relação ao espaço restante do retângulo principal. Embaixo desse retângulo, após um espaçamento, há outro retângulo do mesmo modelo, mas com dados diferentes. Depois dele há uma lista bem espaçada com as siglas dos demais dias da semana, seguidos do dia do mês correspondente, então "qua - 3", "qui - 4" e "sex - 5".

Notamos que temos uma tela inicial com uma App Bar de cor preta e alguns itens em uma lista. Esses itens variam se o dia foi preenchido com alguma informação ou não. Quando o dia é preenchido com uma informação, temos em destaque o dia da semana e do mês, além de um trecho do começo da anotação da pessoa.

Se o dia não foi preenchido, temos apenas o espaço com o dia da semana e do mês. Clicando no dia que não foi preenchido, vamos para uma tela onde podemos escrever um texto e salvá-lo, registrando esse dia na lista.

Topo da tela de registro do aplicativo "Diário Simples". Na parte superior há uma App Bar onde, no canto esquerdo, há uma seta apontado para esquerda. À direita da seta está escrito "quarta-feira, 3 do 8 de 2022". No canto direito da App Bar temos um sinal de confirmação para salvar o registro. Abaixo da App Bar temos um campo em branco, onde o texto é escrito.

Outro recado extremamente importante é sobre as versões. Sabemos que o Flutter se atualiza com muita frequência. Às vezes essas atualizações acabam quebrando o código, o que pode prejudicar seu o entendimento e avanço do curso.

Então recomendo fortemente que utilizem a versão 3.0.5 do Flutter, com a versão 2.17.6 do Dart. Conforme instalarmos as dependências durante o curso, também reforçaremos sobre a questão das versões, para evitar o máximo de frustração possível.

Além disso, aprenderemos algumas funcionalidades técnicas durante o curso. Aprenderemos sobre temas e fontes, e como usar isso a nosso favor para construirmos uma aplicação o mais parecida possível com o protótipo. É um tema bem interessante e é sempre bom revisarmos e aprendê-lo durante os cursos de Flutter.

Também aprenderemos a criar IDs únicos, usando o UUID, e entenderemos um pouco sobre como a Internet funciona, para servir de base para os nossos entendimentos de comunicação com a Web API. Descobriremos como configurar uma API local, como instalar a biblioteca HTTP e como usá-la para fazer requisições para nossa API.

Além disso, aprenderemos a usar interceptadores e loggers para tornar a visualização das nossas requisições mais agradável. Também aprenderemos a converter um objeto para texto, para que ele possa ser mandado pelo canal da Internet e possa ser interpretado ao chegar no servidor.

E claro, como é Flutter, aprenderemos a fazer isso tudo criando e configurando telas e widgets, para tornar as aplicações o mais bonitas e eficientes possível. Também entenderemos como criar e configurar telas no Flutter para fazer todo esse trabalho de comunicação.

Estou muito animado para começar essa aventura e espero que vocês também estejam.

Vejo vocês no próximo vídeo.

Até lá!

Entendendo o Projeto base e API REST - Conhecendo o projeto base

Agora que já nos conhecemos, é importante dizer que, na vida real, nem sempre começaremos nossos projetos do zero. Na verdade, é bem comum que tenhamos que dar continuidade a um projeto já iniciado, ou seja, pegar um projeto que alguém já começou e adicionar novas funcionalidades a ele.

Para exercitarmos essa característica, neste curso aprenderemos a partir de um projeto já iniciado. Trata-se de um simples aplicativo de diário, que possui algumas funcionalidades básicas prontas, mas o principal, que é usar a Web API para guardar os dados, ainda não está implementado. Então é o que faremos.

O projeto está disponível nesta atividade. Então vamos conferir detalhadamente o código que já temos para, aos poucos, entendermos o que está pronto.

Primeiramente, vamos analisar o emulador. Notamos que, até o momento, temos apenas uma tela. Essa tela tem uma App Bar de cor azul, com uma data no canto esquerdo, e uma lista de elementos abaixo da App Bar.

Percebemos que há dois tipos de elementos nesta lista. Um dos elementos tem o dia da semana e o dia do mês, no formato "SSS - D", onde "SSS" representa as três primeiras letras do dia da semana e o "D" é o dia do mês.

O outro elemento já tem algumas informações a respeito de um registro. Ele contém o dia do mês mais destacado, no lado esquerdo, e uma parte do texto da entrada, exibido no lado direito. É isso que já temos pronto, agora vamos conferir como isso se comporta no código.

Primeiramente, vamos conferir nossa estrutura de pastas. Ao acessarmos a pasta "lib" no Explorador, notamos que ela contém quatro pastas e a main.dart. Já sabemos que a main.dart é por onde começamos a rodar nosso programa, mas antes vamos conferir as demais pastas.

Começaremos por "lib > models", porque olhar os models de uma aplicação diz muito sobre ela. Na pasta "models" teremos apenas um modelo, que é o journal.dart. "Journal" se traduz do inglês como "Diário", ou seja, journal é a entrada de um diário.

Ao abrirmos o journal.dart, observamos que o código tem quatro propriedades: String id, String content, DateTime createdAt e o updatedAt, que também é um DateTime.

class Journal {
  String id;
  String content;
  DateTime createdAt;
  DateTime updatedAt;

//Código suprimido
}

Então temos um ID (id) e o próprio conteúdo (content), ambos em forma textual, além do "Criado em" (createdAt), que registra quando a entrada no diário foi criada, e o "Atualizado em" (updatedAt), que registra a data da última atualização dessa entrada. Fora isso, se descermos para a linha 15, observamos que já existe um toString() implementado. Assim ele mostrará essas informações quando tentarmos imprimir um objeto instanciado dessa classe.

//Código suprimido

@override
String toString() {
  return "$content \ncreated_at: $createdAt\nupdated_at:$updatedAt";
}

Esse é o nosso "model", agora vamos para a próxima pasta, que é a "lib > database". Precisamos prestar muita atenção ao database.dart. Esse database é virtual e existe para preencher a tela agora, já que ainda não temos os dados vindos de uma Web API. Isso significa que são dados autogerados.

Abrindo novamente o emulador, observamos que temos a mensagem "Entrei na comunidade da Alura no Discord" no dia 6, que é um sábado. Se atualizarmos a aplicativo Flutter, clicando no Hot Restart, e navegarmos pelo App, encontramos três mensagens: uma no dia 31, que é um domingo, uma no dia 2, que é uma terça, e a mesma mensagem do dia 6.

O database.dart tem um pequeno escopo de mensagens que ele gera automaticamente para conseguirmos testar a tela enquanto não temos a funcionalidade da Web API, que implementaremos a seguir. Portanto é isso que o database faz.

Vocês não precisam se preocupar tanto com a forma que esse código funciona, porque o database.dart só está servido de exemplo, mas eu queria esclarecer a linha 22 deste código: a String id = const Uuid().v1(). Ela informa que nossos IDs utilizarão o padrão UUID, que é basicamente um identificador universal único.

É bem comum que as linguagens de programação tenham uma biblioteca que gere um ID único com o padrão UUID, que é um número enorme de 128 bits, representado de forma hexadecimal. Assim, é gerado um ID com uma chance baixíssima de ser repetido, matematicamente falando. Por isso ele é bem legal e é o que usaremos. Aprenderemos mais sobre o UUID posteriormente.

Além disso, o database.dart usa a biblioteca Random() para gerar aquelas informações. Então há um intervalo de dias com algumas possibilidades de entradas no diário, usando mensagens aleatórias. Simples assim.

Na sequência, acessaremos "lib > helpers". Vou apresentar a vocês nossos "helpers", ou seja, nossos "ajudadores". É bem comum termos pastas com funções ou classes que nos ajudam de algum modo e, neste caso, temos duas delas: phrases (frases) e weekday (dia da semana).

No phrases.dart temos as frases que aparecem no aplicativo de forma aleatorizada, então esse arquivo é bem tranquilo de entender. Já no arquivo weekday.dart, observamos que temos um int weekday na linha 3, dentro da classe WeekDay.

O weekday varia de 1 a 7, representando de segunda a domingo, então transformamos esse número em uma entrada textual que mostramos na tela. Para cada um dos números, criamos, a partir da linha 7, uma entrada curta (short), por exemplo "dom", e uma entrada longa (long), por exemplo, "Domingo". Portanto, com uma instância da classe WeekDay, conseguimos ter uma formatação do dia para usarmos no nosso código.

Por fim, chegaremos nas nossas telas, acessando "lib > screens > home_screen". Por enquanto, temos apenas a home screen, no arquivo home_screen.dart, mas para cada tela que fizermos, criaremos uma pasta dentro de "screens" com o nome da tela, por exemplo "home_screen".

Caso queiramos modularizar alguns widgets, também criaremos a pasta "widgets" dentro da pasta com o nome da tela, como aconteceu com a Home Screen. Portanto, dentro da pasta "home_screen", temos a pasta "widgets" e o arquivo home_screen.dart.

Primeiramente, vamos abrir a home_screen.dart, inclusive podemos fechar o Explorador para vermos melhor o código. A Home Screen é um Stateful Widget onde teremos um dia, que é a data de hoje. Futuramente podemos até fazer uma página para voltarmos aos históricos antigos, mas basicamente temos o dia atual.

A partir desse dia, definiremos o tamanho da janela a ser visualizado. Voltando para o emulador e rolando até o final da tela, notamos que começa com o dia 8. Ao rolarmos para o começo da lista, na parte de cima da tela, notamos que acaba no dia 29.

Isso significa que temos uma janela de 20 dias para visualizarmos nossas entradas, sendo 10 dias na parte de cima da tela e 10 dias na parte de baixo. Além disso, precisamos prestar muita atenção na linha 22 do home_screen.dart.

Map<String, Journal> database = {}

Nessa linha estamos inicializando nossa variável database, que é o um Map<> de String para Journal, onde a String é o ID e o Journal é uma entrada no nosso diário. Com isso, a tela consegue mostrar as entradas registradas, ou seja, se existir uma entrada no sábado do dia 6, ela estará no database e aparecerá na tela do nosso app.

Caso não exista um registro, ele mostra um espaço vazio apenas com a data. Assim, no futuro, implementaremos o Click para pessoa adicionar um registro para essa data.

Imagem de parte da tela do aplicativo. No centro superior da imagem está o texto "sex - 5", seguido por um espaço vazio. Após esse espaço, temos um retângulo no modelo de registro do Diário que vimos na apresentação da aplicação. No centro do quadrado cinza está o número 6 e, abaixo dele, está escrito "sáb". À direita temos o texto "Entrei na comunidade da Alura no Discord!" centralizado no retângulo.

Além disso, no home_screen.dart temos a criação dessa tele que vemos no aplicativo. Portanto, na linha 41, dentro do body, temos uma ListView() com um controller, onde vamos controlar o comportamento de scroll (rolagem) dessa lista. Com isso, posteriormente conseguiremos acessar o ponto da lista que quisermos.

Como filho (children) da ListVIew(), na linha 43 temos o método generateListJournalCards(), que apresentarei na sequência. Esse método gera uma lista com esses cards que temos na tela, e chegaremos a ele em breve. Por fim, na linha 52 da home_screen, temos uma função de refresh() para essa lista.

  void refresh() {
    setState(() {
      database = generateRandomDatabase(maxGap: windowPage, amount: 3);
    });
  }

Agora vamos conferir o método generateListJournalCards, acessando "lib > screens > home_screen > widgets > home_screen_list.dart". Não precisaremos alterar esse método, porque a lógica dele já está pronta. Só alteraremos no database quando estivermos usando a Web API. Contudo vou explicar como ele funciona.

O generateListJournalCards gera uma lista de cards vazios, como observamos na linha 9. Esses cards vazios são aqueles que, no aplicativo, têm apenas o dia da semana e do mês, como "sex - 5". Depois ele confere o database, que passamos via parâmetro, como na linha 17, e onde tiver uma data com um journal ou algo escrito, ele transforma em cartão.

Portanto no dia em que a pessoa adicionou uma entrada no diário, ele mostra o card de conteúdo no aplicativo, que é o card com o dia do mês e da semana em destaque e parte do registro. Se o dia não tiver conteúdo, ele manterá o card vazio, conforme o código da linha 12. O retorno do generateListJournalCards é uma lista na forma de um widget chamado Journal Card.

Se redirecionarmos o código para JournalCard, vamos para o segundo arquivo da pasta "widgets", que é o journal_card.dart. Notaremos que ele é um StatelessWidget que mostra, finalmente, a lista na tela.

Então vamos recapitular em tudo que conhecemos até agora. Temos uma estrutura de pastas compostas de, basicamente: database, helpers, models, screens e do arquivo main.dart, onde rodaremos o código.

Na "models" é onde temos nosso modelo do journal, que representa a entrada que queremos fazer no nosso diário. O arquivo da "database" serve para, enquanto não tivermos um banco de dados de verdade, conseguirmos acessar aleatoriamente alguns exemplos de registro para construirmos nossas telas.

Na pasta "helpers" temos arquivos que nos ajudam a mostrar as coisas de forma mais veloz e ágil, de acordo com o que queremos. Já na pasta "screens", onde temos nossas telas, temos o arquivo da ListView que gera alguns desses cards, dependendo do que tem no database.

Por último, vale ressaltar que estamos usando rotas nomeadas, então, como falei no vídeo anterior, é bem importante que vejam o Alura+ de Flutter sobre rotas nomeadas. Apesar disso, não muito complicado, como podemos observar na linha 18 da main.dart.

Basicamente definimos, através de um Map, quais são nossas rotas, com o routes: {}. Além disso, como mostra a linha 17, definimos qual é a rota inicial através da inicialRoute.

Espero que tenham compreendido e vejo vocês logo mais, quando transformaremos esse projeto que já está rodando em algo cada vez mais parecido com o que vimos no protótipo.

Entendendo o Projeto base e API REST - Organizando nossa aplicação

Antes de irmos para a Web API, é importante saber que, ao trabalharmos um projeto já iniciado, é bem normal precisarmos fazer algumas alterações para ele se tornar apto para receber nossas novas funcionalidades. Pensando nisso que, neste vídeo, vamos mudar a aparência do nosso projeto para ele ficar mais parecido com o que foi pedido no protótipo.

Vamos para o código da main.dart, porque é nele onde começaremos. Como sabemos, o Material App tem algumas propriedades muito impactantes na nossa aplicação, sendo algumas delas relacionadas ao tema. Por exemplo, temos o theme, que significa "tema", então vamos codá-lo na linha 15.

Ao passarmos mouse sobre ele, descobrimos que ele espera um ThemeData. Já existem alguns temas pré-definidos, mas também podemos criar o nosso. Sendo assim a linha 15 fica theme: ThemeData(),.

//Código suprimido

return MaterialApp(
  title: 'Simple Journal',
  debugShowCheckedModeBanner: false,
  theme: ThemeData(),
  darkTheme: ThemeData.dark(),
  themeMode: ThemeMode.light,
  initialRoute: "home",
  routes: {
    "home": (context) => const HomeScreen(),
  },
);

Algo que podemos notar é que já existiam alguns códigos nesse arquivo. Acabamos de criar o nosso tema, mas já existia o darkTheme, que é o tema escuro, na linha 16, e o themeMode, que é o modo do tema, na linha 17.

No themeMode, escolheremos entre o modo de tema claro, que é o que vamos configurar neste vídeo, e o escuro, que poderíamos fazer com outra configuração de cores e comportamentos baseado em um tema escuro. Assim a pessoa conseguiria definir tanto via aplicativo ou via sistema se ela quer ver o tema claro ou escuro.

Para exemplificar, se observamos a linha 17, percebemos que o tema ligado por padrão é o claro: ThemeMode.light. Além disso, no dispositivo, reparamos que o fundo da tela é branco e os componentes da tela tem cores claras, como esperamos em um tema claro.

Como também vimos, na linha 16 ele tem uma predefinição do ThemeData para o modo escuro, ou seja, ThemeData.dark(). Se mudarmos o final da linha 17 para ThemeMode.dark, ao invés de exibir o app com o tema da linha 15, ele usa o tema da linha 16. Vamos salvar e, após o Hot Reload, notamos que o aplicativo mudou para o modo escuro.

Tela do aplicativo em modo escuro. A App Bar está cinza, mas a fonte continua branca. O fundo de tela do aplicativo está em um cinza mais escuro que o da App bar, com os textos também em fonte branca. No cartão de entrada, o quadrado com o dia do mês em destaque agora é dar cor preta e a cor da fonte, tanto no quadrado, quanto nos outros espaços do cartão, também são brancas.

Entretanto, o tema escuro é mais difícil de mudarmos até chegarmos ao tema do protótipo do que o tema claro. Sendo assim, na linha 17, voltaremos o código para ThemeMode.light e faremos as alterações a partir do tema claro mesmo.

A primeira coisa que mudaremos é uma propriedade chamada primarySwatch, então vamos codá-la dentro do ThemeData() da linha 15. Swatch significa, basicamente, amostra ou paleta, então primary swatch pode ser traduzido como paleta primária.

Se deixarmos o mouse sobre o primarySwatch, a documentação nos informa que ela espera uma MaterialColor. Nesse momento, isso significa que não é toda cor pré-definida ou criada via ARGB, que conseguiremos passar, porque essas são colors (Color), enquanto é esperado uma MaterialColor.

A diferença entre uma Color e uma Material Color, além do nome, é que a MaterialColor possui várias cores ou gradações de uma mesma cor, e é ela que esperamos no primarySwatch. Observaremos isso no exemplo.

Então, na linha 16, codaremos Color.. Isso abre um menu de opções que, inclusive, nos possibilitaria criar nossa própria cor, contudo usaremos o .grey. Portanto a linha 16 fica primarySwatch: Colors.grey.

//Código suprimido

theme: ThemeData(
  primarySwatch: Colors.grey,
),

Ele aceitou o .grey e, ao voltarmos para o aplicativo, conseguimos observar o que mudou. A mudança mais significativa está na cor da App Bar, que agora está cinza.

Vamos analisar o que acontece se quiséssemos criar uma cor, como o vermelho com .fromARGB(a, r, g, b). Na linha 15 vamos substituir o .grey por .fromARGB(255, 255, 0, 0), ou seja, o alpha e o vermelho são 255 e o verde o azul são 0. Usamos um vermelho em intenso, mas não funciona e logo temos uma marcação de erro.

Isso acontece porque o primarySwatch espera uma MaterialColor, mas demos uma Color. Para finalizar esse assunto de Color e MaterialColor, se voltarmos a linha 17 para Colors.grey e usaremos o "Ctrl + Botão direito do mouse" sobre o .grey para acessarmos a documentação.

O comando abre o arquivo colors.dart e nele reparamos que a MaterialColor grey tem vários códigos de cor dentro dela, além da cor principal, que é o cinza que estamos vendo. Neste caso, a cor principal está na linha 1834: 500: Color(_greyPrimaryValue).

O primarySwatch espera um Material Color porque ele não usa apenas a cor principal. Para cada detalhe, como a sombra do botão, tipos diferentes de botões e até a App Bar, ele usa uma gradação diferente baseada em um padrão. Por isso ele espera uma amostra de cores, que é o caso de uma MaterialColor, portanto usaremos o Colors.grey no primarySwatch.

Mesmo assim percebemos que nossa App Bar está diferente daquela no nosso protótipo. Existe uma forma de mudarmos isso diretamente na ThemeData(), usando a propriedade appBarTheme. Com ela conseguimos mudar todas as App Bars da nossa aplicação a partir do ThemeData().

Isso é muito importante. Imaginem que temos esse padrão e precisamos aplicá-lo nas App Bars de uma em uma. Isso demora bastante e não é eficiente. Além disso, se tivermos que mudar algo, teria que mudar em todas, o que não é legal.

Portanto a melhor forma de fazer isso é mudando com o appBarTheme, de forma que todas recebam o mesmo padrão. E se quisermos uma especificidade em alguma App Bar, mudamos diretamente nela.

Antes de começarmos esse processo, vamos analisar bem a nossa App Bar atual. Na tela do aplicativo, observamos que a App Bar está cinza, mas segundo o protótipo, ela será preta. Ela também está com uma sombra, que não queremos, e não podemos manter o texto preto, porque ele sumirá na barra preta. Então queremos o texto branco. São essas as alterações que queremos fazer, por enquanto, na nossa App Bar.

Voltando para o código, deixaremos o mouse sobre o appBarTheme para descobrirmos o que ele recebe, que é justamente um AppBarTheme(). Então, na linha 17, codamos appBarTheme: AppBarTheme().

Começaremos corrigindo a cor de fundo. Sendo assim, nos parênteses (()), codaremos color e, dentre as opções de menu, selecionamos a backgroundColor. Nesse caso não precisamos de uma MaterialColor, apenas de uma Color, então podemos passar qualquer cor, no caso, Colors.black.

//Código suprimido

theme: ThemeData(
  primarySwatch: Colors.grey,
  appBarTheme: AppBarTheme(backgroundColor: Colors.black),
),

Vamos salvar e executar o aplicativo. Ao abrirmos novamente o dispositivo, reparamos que a App Bar está completamente preta. Não é exatamente o que queríamos, mas estamos chegando em algum lugar.

Sendo assim, o segundo ponto é mudarmos o estilo do texto, para que ele fique branco. Portanto, depois da backgroundColor, usaremos o titleTextStyle: TextStyle(), que usamos bastante. Dentro dos parênteses passaremos o color: Colors.white.

Por fim, vamos formatar o código e salvar. No caso, ele está com uma marcação informando que esse código precisa ser const, já que não há nenhuma variável envolvida, mas cuidaremos disso no final.

//Código suprimido

theme: ThemeData(
  primarySwatch: Colors.grey,
  appBarTheme: AppBarTheme(
    backgroundColor: Colors.black,
    titleTextStyle: TextStyle(color: Colors.white),
  ),
),

Quando voltamos para o aplicativo, percebemos que o texto da App Bar está na cor branca e permaneceu no lado esquerdo, mas ficou com uma fonte menor, como no protótipo. Então falta apenas removermos a sombra abaixo da App bar, e fazemos isso usando outra propriedade da appBarTheme, chamada elevation.

Portanto, na linha 18, como primeira propriedade, codamos elevation: 0,. Depois vamos formatar e salvar o código para rodar o aplicativo.

Quando o app abre, observamos que a sombra sumiu. Sendo assim, agora podemos voltar para o código e adicionar o const na linha 17, antes de AppBarTheme(), para não termos o linter, que é a marcação que nos lembra do const.

//Código suprimido

theme: ThemeData(
  primarySwatch: Colors.grey,
  appBarTheme: const AppBarTheme(
      elevation: 0,
      backgroundColor: Colors.black,
      titleTextStyle: TextStyle(
          color: Colors.white
      )
  ),
),

//...

O último detalhe que falta é adicionarmos a fonte que esperamos. Existem várias formas de adicionarmos as fontes, mas usaremos o método que é através do Google Fonts. Assim conseguiremos ter acesso a qualquer fonte do Google Fonts, o que é bem legal. Então vamos para o navegador para aprendermos como fazer.

Quem desenvolve em Front-End conhece muito bem o Google Fonts. Caso vocês ainda não conheçam, esse aqui é o repositório de fontes gratuitas da Google, onde conseguimos acessar diversas fontes.

Para acessarmos essas fontes no nosso repositório Dart, existe uma dependência. Então vamos acessar o pub.dev e na barra de busca digitamos "google fonts".

Vamos observar os resultados da busca com atenção para escolhermos a opção correta. A "google_font", que usaremos, é certificada pelo "material.io", possui a tag "Flutter Favorite" e, no canto superior direito do resultado, notamos que ela tem popularidade de 100%.

Busca no pub.dev pela "google fonts". Na parte superior tem um retângulo com fundo azul marinho. No canto superior esquerdo desse retângulo tem a logo do dart e o título "pub.dev", enquanto no canto superior direito tem as opções "Sing in" e "Help". Um pouco abaixo e centralizado dentro do retângulo azul marinho, está o campo de busca escrito "google fonts". Em seguida, sobre um fundo branco, há uma coluna no lado esquerdo com as opções de filtro por plataforma, enquanto no centro da página temos os resultados da busca. O primeiro deles é o "google_fonts", que está contornado por um retângulo vermelho junto com todas as suas especificações. Ele tem a certificação e a tag mencionadas pelo instrutor, assim como 100% de popularidade. Abaixo dele há outro resultado, no qual já é possível observar que não atende todos os critérios.

Clicaremos na extensão "google_fonts" para acessá-la e depois clicamos em "Installing", que é o quarto botão da barra de opções abaixo do nome e das demais informações sobre a extensão. Descendo um pouco a página, acessaremos o código que usaremos, com a versão 3.0.1.

dependencies:
  google_fonts: ^3.0.1

Mais uma vez conversaremos sobre versões, porque é possível que o "google_fonts" esteja em uma versão muito superior a essa no momento em que estiverem assistindo a este curso. Ainda assim, recomendo que usem a versão 3.0.1, que está sendo usada nesse curso, para não termos discrepâncias no aprendizado.

Sendo assim, copiaremos o google_fonts: ^3.0.1 e voltaremos para o nosso código. Em seguida, vamos abrir o explorador do projeto e acessar o arquivo pubspec.yaml. Feito isso, na linha 17, logo abaixo do uuid, adicionaremos o código que copiamos e vamos salvar.

//Código suprimido

dependencies:
  flutter:
    sdk: flutter

  cupertino_icons: ^1.0.2
  uuid: ^3.0.6
  google_fonts: ^3.0.1

Quando salvamos, ele roda para nós o Flutter pub get. Além disso, como já sabemos, por termos criado uma nova dependência, precisamos parar a execução do nosso código e rodar novamente.

Enquanto o app roda, podemos voltar para o main.dart e configurar nosso ThemeData() para receber o google_fonts, o que é bastante simples. Na linha 24, após o fechamento da AppBarTheme(), codamos a propriedade textTheme: e digitamos Go. Com isso, surge um menu de opções onde escolheremos a GoogleFonts que importa automaticamente o pacote de fontes da Google.

theme: ThemeData(
  primarySwatch: Colors.grey,
  appBarTheme: const AppBarTheme(
    elevation: 0,
    backgroundColor: Colors.black,
    titleTextStyle: TextStyle(
        color: Colors.white
    ),
  ),
  textTheme: GoogleFonts
      ),

Em seguida, codaremos um ponto final (.) e, assim, aparece o menu com todas as fontes que disponíveis nessa dependência. A que usaremos, ou seja, a do nosso protótipo, é a bitter. Usaremos na forma de textTheme, que é para onde iremos passar, então codamos GoogleFonts.bitterTextTheme(). Caso quiséssemos usar diretamente em um texto, poderíamos usar apenas GoogleFonts.bitter().

//Código suprimido
theme: ThemeData(
  primarySwatch: Colors.grey,
  appBarTheme: const AppBarTheme(
    elevation: 0,
    backgroundColor: Colors.black,
    titleTextStyle: TextStyle(
        color: Colors.white
    )
  ),
  textTheme: GoogleFonts.bitterTextTheme()
),
//...

Ao salvarmos e voltarmos para o aplicativo, percebemos que nossa fonte já mudou para uma fonte com serifa, que lembra mais uma anotação e diário. Com isso, também deixamos mais parecido com o protótipo. Agora vamos recapitular rapidamente o que fizemos.

Aprendemos que o ThemeData() é o que define como o tema da nossa aplicação irá se comportar. Também descobrimos que podemos variar do modo escuro para o modo claro, e que estamos usando o modo claro, no qual fizemos algumas alterações.

Primeiramente mudamos todas as App Bars para que elas sigam o padrão de cor preta, texto branco e sem sombra. Depois mudamos o tema da fonte para ela ser uma fonte que vem do Google. Para isso, instalamos uma dependência e usamos a fonte .bitter no textTheme.

Agora que está tudo como o esperado, conversaremos sobre conceitos fundamentais para entendermos quando e porque usar Web APIs.

Sobre o curso Flutter com WebAPI: integrando sua aplicação

O curso Flutter com WebAPI: integrando sua aplicação possui 203 minutos de vídeos, em um total de 48 atividades. Gostou? Conheça nossos outros cursos de Flutter em Mobile, ou leia nossos artigos de Mobile.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda Flutter acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas