10 |
11 |
--------------------------------------------------------------------------------
/src/pages/index.module.css:
--------------------------------------------------------------------------------
1 | /**
2 | * CSS files with the .module.css suffix will be treated as CSS modules
3 | * and scoped locally.
4 | */
5 |
6 | .heroBanner {
7 | padding: 4rem 0;
8 | text-align: center;
9 | position: relative;
10 | overflow: hidden;
11 | }
12 |
13 | @media screen and (max-width: 966px) {
14 | .heroBanner {
15 | padding: 2rem;
16 | }
17 | }
18 |
19 | .buttons {
20 | display: flex;
21 | align-items: center;
22 | justify-content: center;
23 | }
24 |
--------------------------------------------------------------------------------
/docs/backend/appwrite.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 4
3 | ---
4 | # Appwrite
5 |
6 | [Appwrite](https://appwrite.io) é mais uma excelente opção open-source, porém, com uma abordagem diferente, utilizando o Docker.
7 |
8 | :::info
9 | Sendo assim, você pode hospedar este container onde quiser.
10 | :::
11 |
12 | Possui um conjunto bem robusto de funcionalidades: **autenticação**, **banco de dados**, **armazenamento de arquivos**, **serverless functions.**
13 |
14 | [https://github.com/appwrite/appwrite](https://github.com/appwrite/appwrite)
--------------------------------------------------------------------------------
/docs/backend/supabase.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 3
3 | description: 'Uma excelente alternativa ao Firebase e o melhor: open-source'
4 | ---
5 |
6 | # Supabase
7 |
8 | [Supabase](https://supabase.com) é um projeto 100% open-source e que usa ferramentas opens-source para fornecer serviços de **autenticação**, **banco de dados** e **armazenamento de arquivos** (e _functions serverless_ em breve).
9 |
10 | Em seu nível gratuito, a cota gratuita é bem generosa, facilitando (e muito) o início do desenvolvimento.
11 |
12 | [https://github.com/supabase/supabase](https://github.com/supabase/supabase)
--------------------------------------------------------------------------------
/blog/2022-03-07-nova-versao.md:
--------------------------------------------------------------------------------
1 | ---
2 | slug: nova-versao
3 | title: Nova versão
4 | authors: rubensdemelo
5 | tags: [flutter, flutter para iniciantes, tutorial]
6 | ---
7 |
8 | Depois de 3 anos e quase 130 commits, esta é a nova versão do site. Muita coisa mudou no Flutterverse, mas o desejo em continuar compartilhando conteúdo de qualidade para a comunidade continuam iguais.
9 |
10 | Assim como o Flutter evoluiu, o flutterparainiciantes.com.br também não poderia ficar para trás.
11 |
12 | Conteúdo revisado && atualizado. O site está muito mais completo.
13 |
14 | E agora tem um blog.
15 |
16 | Tudo para deixar o seu aprendizado mais fácil.
17 |
18 | Até mais ✌️
--------------------------------------------------------------------------------
/docs/app1-rock-in-rio/parte-3-tela-inicial.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 3
3 | ---
4 |
5 | # Parte 3 - Tela inicial
6 |
7 |
10 |
11 | Para capturar a entrada do usuário, utiliza-se `TextField`.
12 |
13 | Também é necessário adicionar um `TextEditingController`, pois é através desta classe que conseguimos obter o valor digitado pelo usuário.
14 |
15 | ```dart
16 | final _controller = TextEditingController();
17 | var titulo = "";
18 | ...
19 | //dentro da ListView, o TextField é inserido
20 | TextField(controller: _controller),
21 | ```
--------------------------------------------------------------------------------
/sidebars.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Creating a sidebar enables you to:
3 | - create an ordered group of docs
4 | - render a sidebar for each doc of that group
5 | - provide next/previous navigation
6 |
7 | The sidebars can be generated from the filesystem, or explicitly defined here.
8 |
9 | Create as many sidebars as you want.
10 | */
11 |
12 | // @ts-check
13 |
14 | /** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */
15 | const sidebars = {
16 | // By default, Docusaurus generates a sidebar from the docs folder structure
17 | tutorialSidebar: [{type: 'autogenerated', dirName: '.'}],
18 |
19 | // But you can create a sidebar manually
20 | /*
21 | tutorialSidebar: [
22 | {
23 | type: 'category',
24 | label: 'Tutorial',
25 | items: ['hello'],
26 | },
27 | ],
28 | */
29 | };
30 |
31 | module.exports = sidebars;
32 |
--------------------------------------------------------------------------------
/docs/20-composicao.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 20
3 | ---
4 |
5 | # Composição
6 |
7 | Entender a diferença entre composição sobre herança, no contexto de um aplicativo em Flutter, facilitará o entendimento de como os widgets se relacionam.
8 |
9 | Composição: Widget X possui o widget Y.
10 |
11 | Herança: Widget X é um widget Y (já que X é filho de Y).
12 |
13 | Lembrando que widgets são pequenos "blocos", fica simples de entender o motivo de Flutter utilizar esse conceito. Conforme formos montando vários blocos, nosso aplicativo vai tomando forma. Esta montagem dos blocos é a composição.
14 |
15 |
10 |
11 | Adicionado a navegação para `AtracaoPage`, utilizando a função `onTap` do `ListTile`.
12 |
13 | É necessário informar também qual é a atração que iremos detalhar, ou seja, qual foi atração selecionada pelo usuário.
14 |
15 | ```dart
16 | return ListTile(
17 | ...
18 | onTap: () {
19 | Navigator.push(
20 | context,
21 | MaterialPageRoute(
22 | builder: (context) =>
23 | AtracaoPage(atracao: listaAtracoes[index])));
24 | },
25 | );
26 | ```
27 |
28 |
--------------------------------------------------------------------------------
/docs/backend/amplify.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 2
3 | ---
4 |
5 | # Amplify
6 |
7 | A maior provedora de serviços em núvem do mundo, possui um framework específico para facilitar o desenvolvimento e de aplicativos móveis e web: o [AWS Amplify](https://docs.amplify.aws/).
8 |
9 | Já consolidado por ser utilizado com outras plataformas, ele está disponível para o Flutter também, porém, em **developer preview** \(ou seja, não recomendado para o uso em ambiente de produção\).
10 |
11 | Mesmo assim, já é possível usufruir de algumas funcionalidades, como **autenticação**, **analytics**, **armazenamento de arquivos**, **banco de dados NoSQL** \(com suporte à offline-mode\) e **APIs** \(REST e Graphql\).
12 |
13 | Vale a pena acompanhar de perto a evolução do framework para o Flutter, pois certamente em breve ele será uma opção de backend para o seu aplicativo:
14 |
15 | [https://github.com/aws-amplify/amplify-flutter](https://github.com/aws-amplify/amplify-flutter)
16 |
--------------------------------------------------------------------------------
/docs/app1-rock-in-rio/parte-4-favoritos.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 4
3 | ---
4 |
5 | # Parte 4 - Favoritos
6 |
7 |
10 |
11 | ## O que é async / await?
12 |
13 | São palavras-chave que permitem que você escreva código assíncrono de forma mais simples e direta.
14 |
15 | ## Como funciona?
16 |
17 | A execução de um método assíncrono é pausada até que o resultado seja retornado. O método assíncrono retorna um Future.
18 |
19 | ## Como usar?
20 |
21 | Marcando um método como assíncrono, você pode usar a palavra-chave `await` para esperar o resultado de um Future.
22 |
23 | ## Exemplo
24 |
25 | ```dart
26 | Future operacaoAssincrona() async {
27 | print('Início do evento assíncrono');
28 | await Future.delayed(Duration(seconds: 2));
29 | print('Fim do evento assíncrono');
30 | }
31 | ```
32 |
--------------------------------------------------------------------------------
/docs/app2-books/parte-7-estilizacao.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 7
3 | ---
4 |
5 | # Parte 7 - Estilização
6 |
7 |
10 |
11 | O método abaixo é o responsável por consultar na API do Google Books, utilizando as palavras-chave `async` e `await`.
12 |
13 | ```dart
14 | void _buscarLivros() async {
15 | final url = Uri.https(
16 | 'www.googleapis.com',
17 | '/books/v1/volumes',
18 | {'q': '{http}'},
19 | );
20 | final response = await http.get(url);
21 |
22 | if (response.statusCode == 200) {
23 | final jsonResponse = convert.jsonDecode(response.body);
24 | final itemCount = jsonResponse['totalItems'];
25 | print('Number of books about HTTP: $itemCount.');
26 | } else {
27 | print('Request failed with status: ${response.statusCode}.');
28 | }
29 | }
30 | ```
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/docs/13-stateless.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 13
3 | ---
4 |
5 | # Stateless
6 |
7 | Por ser mais simples e não possui estado, não dá trabalho nenhum ao framework. Apenas é construído e pronto, permanece imutável.
8 |
9 | Quando criamos um Stateless widget, o Flutter executa o seu construtor e em seguida o método [build()](https://api.flutter.dev/flutter/widgets/StatelessWidget/build.html).
10 |
11 | 
12 |
13 | ```dart
14 | class MeuWidgetImutavel extends StatelessWidget {
15 |
16 | @override
17 | Widget build(BuildContext context) {
18 | return const Text('Eu não terei meu estado alterado');
19 | }
20 | }
21 | ```
22 |
23 | A anatomia de um **Stateless** widget é esta: basicamente precisamos sobrescrever o método [build()](https://api.flutter.dev/flutter/widgets/StatelessWidget/build.html) para indicarmos ao Flutter como deve ser o nosso `MeuWidgetImutavel` , (neste caso apenas um texto).
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/blog/2023-01-23-bloc-o-padrao-e-o-package.md:
--------------------------------------------------------------------------------
1 | ---
2 | slug: bloc-o-padrao-e-o-package
3 | title: BLoC - O padrão e o package
4 | authors: rubensdemelo
5 | tags: [flutter, bloc, package]
6 | ---
7 |
8 | 
9 |
10 | Gerenciamento de estado com Flutter é um tópico bem amplo e neste post vamos explorar (um pouco) sobre o tão conhecido BLoC!
11 |
12 | BLoC e bloc_library **não** são a mesma coisa! É crucial entender que, apesar do nome, eles representam coisas diferentes.
13 |
14 | O padrão *BLoC* é uma arquitetura que separa a lógica de negócios da interface do usuário.
15 |
16 | O package *bloc_library* é uma implementação concreta desse padrão.
17 |
18 | O *pattern* e o *package* são distintos.
19 |
20 | O *pattern* foi apresentado pelo Google na DartConf em 2018. Foi a arquitetura escolhidas para compartilhar a lógica de negócio entre um aplicativo Flutter e uma aplicação AngularDart, utilizando Streams.
21 |
22 | O *package* implementa esta arquitetura, abstraindo e facilitando a implementação do pattern. E deu tão certo que é um dos packages mais populares para gerenciamento de estado.
23 |
24 | E é essencial reconhecer que o *pattern* em si é independente e pode ser implementado sem este *package*.
--------------------------------------------------------------------------------
/docs/21-declarativo.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 35
3 | ---
4 |
5 | # Declarativo
6 |
7 | Este conceito merece um destaque especial, pois muda a forma como estamos acostumados a construir interfaces. Apesar de não ser um conceito novo, vem sendo cada vez mais adotado e ganhando popularidade na comunidade, devido à facilidade que ele proporciona, não só de construir, como também em entender nossa interface.
8 | Com a imagem abaixo, ficará mais fácil acompanhar a explicação:
9 |
10 | 
11 |
12 | Nossa interface, reflete o estado da nossa aplicação. Sempre que o estado da aplicação muda, os widgets são reconstruídos para atender aquele novo estado. Seja um botão ou ícone que muda de cor após ser pressionado ou até mesmo toda uma tela após o usuário logar no aplicativo.
13 |
14 |
15 |
16 |
17 |
18 | :::tip Jetpack Compose e Swift UI
19 |
20 | Os novos kits de desenvolvimento para Android e iOS, respectivamente, utilizam esta abordagem.
21 |
22 | :::
--------------------------------------------------------------------------------
/docs/9-main-dart.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 9
3 | ---
4 |
5 | # main.dart
6 |
7 | O ponto de partida de qualquer aplicativo em Dart. Por padrão, utiliza-se um arquivo chamado `main.dart` com a chamada ao método `main()`.
8 |
9 | ```dart
10 | void main() {
11 | print('Hello, World!');
12 | }
13 | ```
14 |
15 | No Flutter, método `runApp` é o responsável por executar o aplicativo.
16 |
17 | ```dart
18 | import 'package:flutter/material.dart';
19 |
20 | void main() {
21 | runApp(SuperApp());
22 | }
23 |
24 | class SuperApp extends StatelessWidget {
25 | @override
26 | Widget build(BuildContext context) {
27 | return MaterialApp(
28 | title: 'SuperApp',
29 | home: Scaffold(
30 | appBar: AppBar(
31 | title: Text('SuperApp'),
32 | ),
33 | body: Center(
34 | child: Text('Hello, SuperApp!'),
35 | ),
36 | ),
37 | );
38 | }
39 | }
40 | ```
41 |
42 | #### Este vídeo aborda o `main.dart` em detalhes:
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/docs/10-material-app.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 10
3 | ---
4 |
5 | # MaterialApp
6 |
7 | É a raiz de um aplicativo Flutter, fornecendo uma estrutura base para:
8 |
9 | **Navegação:** Todas as rotas são gerenciadas pelo `MaterialApp`, facilitando a navegação entre diferentes telas. Logo, a "página inicial" também é definida aqui.
10 |
11 | **Estilização:** Cores, fontes, textos e todos os outros widgets visuais são descendentes de um `MaterialApp`. Ele se utilizada das definicões do [Material Design](https://m3.material.io), sendo assim, visualmente o seu aplicativo já ter
12 |
13 | **Internacionalização:** Se o aplicativo suportar mais de 1 idioma, precisa também ter a configuração feita no `MaterialApp`. Por padrão, o idioma definido é o `en-US`. Utilizando o código abaixo, o nosso idioma entra em ação.
14 |
15 | ```dart
16 | return MaterialApp(
17 | ...
18 | locale: const Locale('pt', 'BR'),
19 | ...
20 | );
21 | ```
22 | #### Este vídeo aborda o `MaterialApp` em detalhes:
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/docs/gerenciamento-estado/gerenciamento-estado.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 1
3 | ---
4 |
5 | # Gerenciamento de estado
6 |
7 | No Flutter, **estado** se refere a qualquer conjunto de dados que pode mudar ao longo do tempo e afetar a interface do usuário.
8 |
9 | Conforme os aplicativos se tornam mais complexos, gerenciar de forma eficiente essas mudanças dinâmicas nos dados se torna essencial para manter a experiência do usuário simples e contínua.
10 |
11 | O Flutter oferece uma variedade de abordagens de gerenciamento de estado, cada uma atendendo a diferentes requisitos de projeto. Desde o método `setState()` para gerenciar o estado local do widget até soluções mais avançadas como BLoC e packages como o bloc_library, riverpod, MobX.
12 |
13 | Gerenciamento de estado no Flutter é crucial para criar aplicativos que sejam eficientes e de fácil manutenção, garantindo que a interface do usuário permaneça sincronizada com os dados e proporcionando uma experiência previsível e agradável ao usuário.
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/docs/38-testes.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 38
3 | description: 'Disciplina importante em qualquer projeto de software, no Flutter não seria diferente.'
4 | ---
5 |
6 | # Testes
7 |
8 | Disciplina importante em qualquer projeto de software, no Flutter não seria diferente.
9 |
10 | Unitário e integração são tipos de testes já conhecidos no universo da programação.
11 |
12 | 
13 |
14 |
15 |
16 |
17 |
18 | # Testes de widget
19 |
20 | Existe uma "categoria" especial, que são os testes de widget. Utilizados para validar a interface do aplicativo. Lembre-se, no Flutter, tudo são widgets. Uma vez testados, podemos garantir que a interface tem os elementos e comportamentos esperados.
21 |
22 | Utiliza-se o pacote `flutter_test`.
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/docs/19-framework.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 19
3 | description:
4 | 'Entenda o framework e como seu código se conecta com o Flutter'
5 | ---
6 |
7 | # Framework
8 |
9 | Esta organização em camadas, possibilita que cada uma delas seja independente. Compostas por diferentes pacotes, que podem ser extendidos e também substituídos.
10 |
11 | 
12 |
13 | import Tabs from '@theme/Tabs';
14 | import TabItem from '@theme/TabItem';
15 | import FrameworkSvg from '/img/framework.svg';
16 | import EngineSvg from '/img/engine.svg';
17 | import EmbedderSvg from '/img/embedder.svg';
18 |
19 |
20 |
21 | APIs prontas para serem utilizadas no aplicativo.
22 |
23 |
24 |
25 | Compila o código Dart em instruções binárias.
26 |
27 |
28 |
29 | Interage com o sistema operacional.
30 |
31 |
32 |
33 |
34 |
10 |
11 |
12 | A variável `itemCount` foi criada e inicializada com o valor `0`.
13 |
14 | Então, o seu valor é atualizado após a consulta a API ter retornado o `totalItems`.
15 |
16 | Ao invocar o setState(), o Flutter irá reconstruir o widget, com o novo valor de `itemCount`.
17 |
18 | Assim, a tela é atualizada sempre que uma nova consulta for feita.
19 |
20 | ```dart
21 | var itemCount = 0;
22 |
23 | //antes
24 | if (response.statusCode == 200) {
25 | final jsonResponse = convert.jsonDecode(response.body);
26 | final itemCount = jsonResponse['totalItems'];
27 | ...
28 | Text(
29 | 'Foram encontrados X livros sobre $titulo ',
30 |
31 | //depois
32 | if (response.statusCode == 200) {
33 | final jsonResponse = convert.jsonDecode(response.body);
34 | itemCount = jsonResponse['totalItems'];
35 | setState((){});
36 | ...
37 | Text(
38 | 'Foram encontrados $itemCount livros sobre $titulo ',
39 | ```
--------------------------------------------------------------------------------
/docs/18-arquitetura.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 18
3 | description: 'Entender a arquitetura do Flutter é importante, precisamos entender toda a "anatomia" dos nossos aplicativos.'
4 | ---
5 |
6 | # Arquitetura
7 |
8 | Entenda onde o seu código se "encaixa" nesta estrutura.
9 |
10 | import Tabs from '@theme/Tabs';
11 | import TabItem from '@theme/TabItem';
12 |
13 |
14 |
15 | Código do aplicativo, dependências, arquivos estáticos (imagens, fontes, etc).
16 |
17 |
18 | O framework em si, também escrito em Dart.
19 |
20 |
21 | Responsável por unir o seu código e o do framework e prepará-los para que sejam executados pelo hardware.
22 |
23 |
24 | Responsável por delegar e controlar as instruções binárias ao hardware.
25 |
26 |
27 | Não precisa de explicação né ?!
28 |
29 |
30 |
31 | 
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/docs/0-introducao.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 0
3 | slug: /
4 | title: Introdução
5 |
6 | ---
7 |
8 | # Introdução
9 |
10 | Flutter é uma ferramenta criada pelo Google para desenvolvimento de aplicativos para 6 plataformas diferentes:
11 |
12 | **Android, iOS, Web, Windows, Linux e macOS**
13 |
14 | E o melhor de tudo: utilizando o mesmo código-fonte.
15 |
16 |
21 |
22 | ---
23 |
24 | **Sobre o livro:** Online e open-source, escrito e mantido desde 2019 por [Rubens de Melo](https://github.com/rubensdemelo).
25 |
26 | **Público-alvo:** Para aqueles que desejam aprender de forma rapida e eficiente.
27 |
28 | **Youtube** Complemento do material escrito em uma playlist no [Youtube](https://www.youtube.com/playlist?list=PLS4cqF1_X2syzBpkoSwtmKoREgnp1MhTn).
29 |
30 | **Conteúdo** Cuidadosamente selecionado e estruturado para valorizar o seu tempo.
31 |
32 | 
--------------------------------------------------------------------------------
/src/pages/old-index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import clsx from 'clsx';
3 | import Layout from '@theme/Layout';
4 | import Link from '@docusaurus/Link';
5 | import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
6 | import styles from './index.module.css';
7 | import HomepageFeatures from '../components/HomepageFeatures';
8 |
9 | function HomepageHeader() {
10 | const { siteConfig } = useDocusaurusContext();
11 | return (
12 |
13 |
14 |
{siteConfig.title}
15 |
{siteConfig.tagline}
16 |
17 |
20 | Começar
21 |
22 |
23 |
24 |
25 | );
26 | }
27 |
28 | export default function Home() {
29 | const { siteConfig } = useDocusaurusContext();
30 | return (
31 |
34 |
35 |
36 |
37 |
38 |
39 |
40 | );
41 | }
42 |
--------------------------------------------------------------------------------
/docs/gerenciamento-estado/local-global.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 2
3 | ---
4 |
5 | # Estado: Local x Global
6 |
7 | Já sabemos que o Flutter utiliza o modelo declarativo para construir a interface. Vamos relembrar:
8 |
9 | 
10 |
11 | Aprofundando um pouco mais sobre o **state** \(estado\), temos dois tipos:
12 |
13 | **Global:** Como o próprio nome sugere, um estado compartilhado por **todo** o aplicativo. Ex: usuário logado ou não. Esta informação deve estar disponível para todos os widgets.
14 |
15 | **Local:** Estado **isolado** de um widget, quando não há a necessidade de compartilhá-lo com nenhum outro widget. Ex: Um botão so é habilitado quando os campos obrigatórios de um formulário estão preenchidos. Portanto, o estado de ativar/desativar tal botão, não precisa ser compartilhado para nenhum outro widget do aplicativo.
16 |
17 | ### Ótimo, entendi a diferença entre estado global e local. E agora?
18 |
19 | Vamos descobrir como implementá-los em Flutter.
20 |
21 | Começaremos pelo estado **local**, por ser o mais simples. Utilizando o [Stateful](https://api.flutter.dev/flutter/widgets/StatefulWidget-class.html) widget.
22 |
23 | Em seguida, abordaremos algumas opções para gerenciar o estado **global**, com 3 opções diferentes: com o [InheritedWidget](https://api.flutter.dev/flutter/widgets/InheritedWidget-class.html), com o package [provider](https://pub.dev/packages/provider) e também o padrão [BLoC](https://www.didierboelens.com/2018/08/
24 |
--------------------------------------------------------------------------------
/docs/app1-rock-in-rio/parte-5-navegacao.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 5
3 | ---
4 |
5 | # Parte 5 - Navegação
6 |
7 |
8 |
9 |
10 |
11 | Precisamos de uma estrutura para armazenar as atrações que foram favoritadas pelo usuário.
12 |
13 | Neste caso, uma lista resolve o problema. Pois assim, adicionamos e removemos os items desta lista, de acordo com a açao do usuário (favoritar / remover).
14 |
15 | ```dart
16 |
17 | final List _listaFavoritos = [];
18 |
19 | return Scaffold(
20 | ...
21 | body: ListView.builder(
22 | itemCount: listaAtracoes.length,
23 | itemBuilder: (context, index) {
24 | final isFavorito = _listaFavoritos.contains(listaAtracoes[index]);
25 | return ListTile(
26 | ...
27 | trailing: IconButton(
28 | onPressed: () {
29 | setState(() {
30 | if (isFavorito) {
31 | _listaFavoritos.remove(listaAtracoes[index]);
32 | } else {
33 | _listaFavoritos.add(listaAtracoes[index]);
34 | }
35 | });
36 | },
37 | icon: isFavorito
38 | ? const Icon(Icons.favorite, color: Colors.red)
39 | : const Icon(Icons.favorite_border),
40 | );
41 | ```
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/src/css/custom.css:
--------------------------------------------------------------------------------
1 | /**
2 | * Any CSS included here will be global. The classic template
3 | * bundles Infima by default. Infima is a CSS framework designed to
4 | * work well for content-centric websites.
5 | */
6 |
7 | /* You can override the default Infima variables here. */
8 | :root {
9 | --ifm-color-primary: #02569b;
10 | --ifm-color-primary-dark: #024d8b;
11 | --ifm-color-primary-darker: #024984;
12 | --ifm-color-primary-darkest: #013c6c;
13 | --ifm-color-primary-light: #025fab;
14 | --ifm-color-primary-lighter: #0263b2;
15 | --ifm-color-primary-lightest: #0370ca;
16 | }
17 |
18 | /* For readability concerns, you should choose a lighter palette in dark mode. */
19 | [data-theme='dark'] {
20 | --ifm-color-primary: #ffc108;
21 | --ifm-color-primary-dark: #edb100;
22 | --ifm-color-primary-darker: #e0a700;
23 | --ifm-color-primary-darkest: #b88a00;
24 | --ifm-color-primary-light: #ffc822;
25 | --ifm-color-primary-lighter: #ffcb2f;
26 | --ifm-color-primary-lightest: #ffd557;
27 | }
28 |
29 | .docusaurus-highlight-code-line {
30 | background-color: rgba(0, 0, 0, 0.1);
31 | display: block;
32 | margin: 0 calc(-1 * var(--ifm-pre-padding));
33 | padding: 0 var(--ifm-pre-padding);
34 | }
35 |
36 | html[data-theme='dark'] .docusaurus-highlight-code-line {
37 | background-color: rgba(0, 0, 0, 0.3);
38 | }
39 |
40 | .video-container {
41 | overflow: hidden;
42 | position: relative;
43 | width:100%;
44 | }
45 |
46 | .video-container::after {
47 | padding-top: 56.25%;
48 | display: block;
49 | content: '';
50 | }
51 |
52 | .video-container iframe {
53 | position: absolute;
54 | top: 0;
55 | left: 0;
56 | width: 100%;
57 | height: 100%;
58 | }
--------------------------------------------------------------------------------
/docs/backend/firebase.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 1
3 | ---
4 |
5 | # Firebase
6 |
7 | [Firebase](https://firebase.google.com/products?hl=pt-br) é o [BaaS](https://pt.stackoverflow.com/questions/298361/o-que-%C3%A9-um-backend-as-a-service-baas) do Google e possui uma vários serviços disponíveis para utilizarmos em nossos aplicativos:
8 |
9 | [Autenticação](https://firebase.google.com/docs/auth/?hl=pt-br): Permite que os usuário se autentiquem para utilizar o seu aplicativo, utilizando e-mail ou redes sociais \(Google, Facebook, Twitter, Github, etc\). Assim você tem acesso à informações como e-mail, nome e até a foto do perfil.
10 |
11 | [Armazenamento](https://firebase.google.com/docs/storage/?hl=pt-br): O Cloud Storage permite que você armazene arquivos \(fotos, vídeos, áudios, etc\) em uma estrutura simples e escalável.
12 |
13 | [Banco de Dados:](https://firebase.google.com/docs/firestore?hl=pt-br) Com o Cloud Firestore, temos um banco de dados NoSQL escalável, com suporte off-line e que pode ser acessado também por aplicativos Web.
14 |
15 | [Serverless](https://firebase.google.com/docs/functions): Que tal enviar um e-mail quando os usuários logarem no seu aplicativo? Ou enviar uma notificação quando um novo evento? Pode ser útil diminuir o tamanho da foto que o usuário fez o upload, certo? Podemos executar todas essas tarefas com o Cloud Functions. Não é preciso ter um servidor para isso. Basta escrever as funções \(em Javascript, Typescript, Python ou Go\) que o Firebase cuida da execução para você.
16 |
17 | Vários outros serviços estão disponíveis e podem ser úteis ao seu aplicativo.
18 |
19 | [https://firebase.google.com](https://firebase.google.com)
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/docs/17-estrutura.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 17
3 | ---
4 |
5 | # Estrutura
6 |
7 | Ao iniciarmos um projeto com o Flutter, a seguinte estrutura é criada:
8 |
9 | 
10 |
11 | import Tabs from '@theme/Tabs';
12 | import TabItem from '@theme/TabItem';
13 |
14 |
15 |
16 | Contém o código Dart do aplicativo. É possível criar pastas e subpastas aqui dentro, porém o arquivo **main.dart** deve estar na raiz.
17 |
18 |
19 | O ponto de partida de qualquer aplicativo em Flutter
20 |
21 |
22 | Arquivos de testes do aplicativo.
23 |
24 |
25 | As pastas android/ios/linux/mac/web/windows são necessárias para executar o aplicativo em cada uma das plataformas.
26 |
27 |
28 | Informações do aplicativo, como nome, versão, dependências e imagens.
29 |
30 |
31 | Metadados das dependências do aplicativo.
32 |
33 |
34 | Configuração do **Analyzer**, a ferramenta para análise estática do código, verificando erros, alertas e lint.
35 |
36 |
37 |
38 | :::tip main.dart
39 |
40 | O método **main()** é o ponto de partida para todo aplicativo Flutter. O seu retorno é sempre _void_.
41 |
42 | ```dart
43 | void main() => runApp(MeuAplicativo());
44 | ```
45 | :::
46 |
47 | A função `runApp()` recebe um widget como parâmetro, ou seja, todo nosso aplicativo também é um widget.
--------------------------------------------------------------------------------
/docs/22-navegacao.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 22
3 | ---
4 |
5 | # Navegação
6 |
7 | Utiliza-se o conceito de [pilha](https://pt.wikipedia.org/wiki/Pilha\_\(inform%C3%A1tica\)) (stack) para executar a navegação no Flutter.
8 |
9 | Para manipular a "pilha" de telas, existe o widget [Navigator](https://api.flutter.dev/flutter/widgets/Navigator-class.html). Com o princípio de **"o último que entra é o primeiro que sai"**, as operações de **push** e **pop**, adicionam e removem as telas da "pilha" de navegação.
10 |
11 | import ThemedImage from '@theme/ThemedImage';
12 | import useBaseUrl from '@docusaurus/useBaseUrl';
13 |
14 |
21 |
22 |
23 | [**Push**](https://api.flutter.dev/flutter/widgets/Navigator/push.html): Para navegar até **TelaB**, utiliza-se o método `push()`.
24 |
25 | ```dart
26 | //push() 'empurra' a TelaB para o topo da pilha
27 |
28 | Navigator.push(
29 | context,
30 | MaterialPageRoute(builder: (context) => TelaB()),
31 | );
32 | ```
33 |
34 | [**Pop**](https://api.flutter.dev/flutter/widgets/Navigator/pop.html): Para voltar à página anterior, utiliza-se o método `pop()`.
35 |
36 | ```dart
37 | //pop() 'puxa' a TelaB para o topo da pilha
38 |
39 | Navigator.pop(context);
40 | ```
41 |
42 |
43 |
44 |
59 |
60 | );
61 | }
62 |
--------------------------------------------------------------------------------
/docs/animacoes/animacoes.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 40
3 | ---
4 |
5 | # Introdução
6 |
7 | O Flutter oferece um excelente suporte para a construção de animações incríveis, uma vez que tudo o que está na tela é "pintado pixel por pixel", graças à biblioteca [Skia](https://skia.org/). E felizmente, elas são extremamente bem documentadas, vale a pena conferir a documentação [oficial](https://flutter.dev/docs/development/ui/animations).
8 |
9 | Elas são dividas em 2 tipos diferentes:
10 |
11 | **Implícitas:** O controle da animação é feito pelo Flutter.
12 |
13 | **Explícitas:** O controle da animação é feito pelo desenvolvedor.
14 |
15 | :::tip Controle ?!
16 | Por **controle**, podemos entender: início, duração e efeito \(basicamente\).
17 | :::
18 |
19 | O significado das palavras ajudará no entendimento:
20 |
21 | [Implícito](https://www.dicio.com.br/implicito/): Aquilo que não se expressa de modo claro.
22 |
23 | [Explícito](https://www.dicio.com.br/explicito/): Que é expresso sem dúvidas nem ambiguidades.
24 |
25 | Ainda não está claro? Sem problemas, explico com mais detalhes.
26 |
27 | Imagine que alguém te delega uma tarefa: **ir ao mercado comprar leite**. A tarefa pode ser delegada da seguinte forma:
28 |
29 | **Implícita:** Vá ao mercado e compre 1 litro de leite.
30 |
31 | **Explícita:** Vá ao mercado, compre 1 litro de leite desnatado, da marca XPTO, antes das 9h da manhã.
32 |
33 | Trazendo para o nosso contexto, nós delegamos ao Flutter a tarefa de animar widgets. Seja mudar da cor vermelho para amarelo, mudar do tamanho de 10 para 30, ir do ponto X para o ponto Y. A animação é a mesma, porém, a forma como delegamos pode ser implícita ou explícita.
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/docs/11-scaffold.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 11
3 | ---
4 |
5 | # Scaffold
6 |
7 | A organização visual e a estruturação das telas são aspectos fundamentais qualquer aplicativo Flutter. O widget `Scaffold` cumpre esta função. Ele fornece uma estrutura básica e que abrange toda a tela, oferecendo elementos comuns, como:
8 |
9 | **AppBar:** É a barra de navegação superior. Contém o título do aplicativo ou da tela, botões ou uma barra de pesquisa.
10 |
11 | **Body:** Esta é a área principal da tela, onde o conteúdo é exibido. Você pode definir qualquer widget como o principal elemento visual da sua tela (listas, imagens, campos de texto, botões, etc).
12 |
13 | **FloatingActionButton:** Este é um botão flutuante que se destaca sobre outros widgets, geralmente localizado no canto inferior direito da tela. É usado para ações principais, como adicionar um novo item ou iniciar uma nova atividade. Possui um design diferenciado e é fácil de ser identificado pelos usuários.
14 |
15 | **BottomNavigationBar:** Uma barra de navegação inferior que permite a rápida troca entre diferentes telas. Utilizado quando se tem entre 3 até 5 opcoes diferentes de navegacao, por exemplo: Feed, Perfil, Mensagens, Configuracoes.
16 |
17 | Conforme você avançar no aprendizado, descobrirá que o Scaffold é apenas a ponta do iceberg. Mas sem dúvida, é um widget indispensável.
18 |
19 | import ThemedImage from '@theme/ThemedImage';
20 | import useBaseUrl from '@docusaurus/useBaseUrl';
21 |
22 | ;
29 |
30 | #### Este vídeo aborda o `Scaffold` em detalhes:
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/docs/14-stateful.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 14
3 | ---
4 |
5 | # Stateful
6 |
7 | Inicialmente, parece ser tão simples quando o [Stateless](https://api.flutter.dev/flutter/widgets/StatelessWidget-class.html) widget, quando criamos nosso widget, o Flutter chama o seu construtor e em seguida o método [createState()](https://api.flutter.dev/flutter/widgets/StatefulWidget/createState.html).
8 |
9 | 
10 |
11 | ```dart
12 | import 'package:flutter/material.dart';
13 |
14 | class MeuWidgetMutavel extends StatefulWidget {
15 | @override
16 | _MeuWidgetMutavelState createState() => _MeuWidgetMutavelState();
17 | }
18 |
19 | class _MeuWidgetMutavelState extends State {
20 | @override
21 | Widget build(BuildContext context) {
22 | return const Text('Eu terei meu estado alterado');
23 | }
24 | }
25 |
26 | ```
27 |
28 | * O uso do "\_" torna o widget privado para o escopo da biblioteca em que ele se encontra;
29 | * O uso de "=>" indica que este método executa apenas 1 função.
30 |
31 | Mas não se engane, pois a diferença não é apenas no nome dos métodos. Lembre-se que ao criar um objeto do tipo [State](https://api.flutter.dev/flutter/widgets/State-class.html), um [Stateful](https://api.flutter.dev/flutter/widgets/StatefulWidget-class.html) widget ganha poderes mutáveis?! Então, é dentro dele que a mágica acontece.
32 |
33 | Nosso `MeuWidgetMutavel` ao ser construído pelo framework, executa o método `createState()` (linha 5) e este por sua vez, executa apenas 1 função, que é instanciar `_MeuWidgetMutavelState`. Ele é um filho de [State](https://api.flutter.dev/flutter/widgets/State-class.html), logo, herda algumas características e comportamentos (linha 8).
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/blog/2023-01-30-aprenda-com-commits-do-flutter-1.md:
--------------------------------------------------------------------------------
1 | ---
2 | slug: aprenda-com-commits-do-flutter-1
3 | title: Aprenda com os commits do Flutter
4 | authors: rubensdemelo
5 | tags: [flutter, bloc, package]
6 | ---
7 |
8 | Hey 👋,
9 |
10 | Hoje vou compartilhar com você um commit bem interessante do repositório do Flutter:
11 |
12 | [Implementing switch expressions in foundation/ and material/](https://github.com/flutter/flutter/pull/142279/files)
13 |
14 | Contém a implementação do "novo" `switch` da linuagem Dart em 2 pacotes importantíssimos do framework: **foundation** e o **material**. É interessante ver na prática como um novo recurso da linguagem agora integra os aplicativos que iremos criar.
15 |
16 | O Dart vem evoluindo e se aperfeiçoando, trazendo funcionalidades já existentes em outras linguagens, tornando-a assim mais robusta e atrativa, especialmente para dessenvolvedores de plataforma nativas que contam com alguns recurso que só existem no Kotlin/Swift.
17 |
18 | Lendo o código antes e depois podemos avaliar o quanto a legibilidade melhora.
19 |
20 | Aqui está o código antigo:
21 | ```dart
22 | switch (parameters['value']) {
23 | case 'Brightness.light':
24 | debugBrightnessOverride = ui.Brightness.light;
25 | case 'Brightness.dark':
26 | debugBrightnessOverride = ui.Brightness.dark;
27 | default:
28 | debugBrightnessOverride = null;
29 | }
30 | ```
31 | Aqui está o código novo:
32 |
33 | ```dart
34 | debugBrightnessOverride = switch (parameters['value']) {
35 | 'Brightness.light' => ui.Brightness.light,
36 | 'Brightness.dark' => ui.Brightness.dark,
37 | _ => null,
38 | };
39 | ```
40 |
41 | Este novo `switch` foi introduzido na versão 3.1, liberada em agosto de 2023. Ou seja, não é uma atualização tão nova assim, mas só agora ela está fazendo parte do Flutter. Deixo aqui o link para você conferir em detalhes: [https://dart.dev/language/branches#switch-expressions](https://dart.dev/language/branches#switch-expressions)
42 |
43 | Espero que você tenha gosta e esta dica tenha sido útil. Dá uma conferida no link do commit, vale a pena!
--------------------------------------------------------------------------------
/docs/16-setState.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 16
3 | ---
4 |
5 | # setState()
6 |
7 | Com certeza este será o seu primeiro contato com alterações de estado em um aplicativo Flutter. O famoso método `setState()`, que é exclusivo ao widgets do tipo [Stateful](https://api.flutter.dev/flutter/widgets/StatefulWidget-class.html). Ao adicionar interatividade em um aplicativo, ele é o mais simples, básico e fácil de entender.
8 |
9 | Quando criamos um novo projeto em Flutter o exemplo inicial é um aplicativo que quando pressionamos um botão, incrementa a quantidade de vezes que o botão foi pressionado:
10 |
11 | ```dart
12 | var contador = 0;
13 | setState(() {
14 | contador ++;
15 | });
16 | ```
17 |
18 | Ao chamar o método `setState()`, nosso widget será reconstruído já com o novo valor da variável `contador` tendo sido incrementado.
19 |
20 | Não tem segredo nenhum aqui, seja incrementando uma variável, fazendo uma requisição à uma API ou qualquer outro evento que altere o estado do nosso widget basta invocar o método `setState()` para que ele seja reconstruído para representar o seu novo estado.
21 |
22 | O grande problema com ele é que à medida que o aplicativo for crescendo e ganhando complexidade, pode ser necessário alterações em vários widgets diferentes, e controlar as chamadas do `setState()` em todas elas acaba ficando inviável. Não que seja **impossível** utilizar esta opção, mas deve-se estar bem maduro para escolhe-la como única forma de gerenciamento de estado.
23 |
24 | O `setState()` é ideal para o estado **local** de um widget, como marcar/desmarcar um checkbox/switch. Para o estado **global** da aplicação \(ex: usuário logado, carrinho de compras\) há outras opções mais robustas e que permitem atualizar vários widgets quando o estado sofrer alterações.
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/docs/36-widget-tree.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 36
3 | ---
4 |
5 | # Widget Tree
6 |
7 | É a estrutura que representa como nossos widgets estão organizados.
8 |
9 | Conforme vamos construindo nosso aplicativo, compondo widgets uns aos outros, esta estrutura pode \(e com certeza vai\) crescendo. Estando ela cada vez maior, fica mais complicado de que a nossa interface represente o estado da nossa aplicação.
10 |
11 | A imagem abaixo é da [documentação](https://flutter.dev/docs/development/data-and-backend/state-mgmt/intro) e ilustra perfeitamente um caso de um carrinho de compras:
12 |
13 | 
14 |
15 | * MyApp - Nosso widget raiz. É por aqui que o aplicativo começa.
16 | * MyLoginScreen - Tela inicial exibida ao usuário.
17 | * MyCatalog - Após o usuário logar, a tela possui uma barra com acesso ao carrinho de compras e também tem acesso à lista de produtos.
18 | * MyCart - Quando o usuário escolhe um produto, este vai para o seu carrinho de compras.
19 |
20 | O ponto chave aqui é a ação do usuário de adicionar um produto ao carrinho de compras. Pois é preciso informar ao MyCart, que seu estado mudou, agora ele possui 1 item \(MyListitem\).
21 |
22 | Neste exemplo, nossa árvore de widgets é pequena. Imagine se dentro do catálogo tivéssemos uma divisão por categorias e sub-categorias ou que no carrinho poderíamos ter lista de desejos, lista de presentes ou o usuário tendo uma tela com detalhes do seu perfil, histórico de todas as compras. Facilmente nossa widget tree ficará maior, mais complexa, mais entrelaçada.
23 |
24 | Sendo assim, temos vários widgets que podem consumir e/ou atualizar o estado da aplicação.
25 |
26 | Sabendo disso, à partir de agora, iremos nos orientar pela "regra" abaixo:
27 |
28 | :::info
29 | Reconstruir apenas a quantidade necessária de widgets quando o estado da aplicação sofrer alterações.
30 | :::
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/static/img/declarative.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/gerenciamento-estado/inherited-widget.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 4
3 | ---
4 |
5 | # InheritedWidget
6 |
7 | Não importa quão grande seja a sua estrutura de widgets, se precisar passar informações no sentido TOP-DOWN \(de cima para baixo\), sem dúvida alguma o [InheritedWidget](https://api.flutter.dev/flutter/widgets/InheritedWidget-class.html) deve ser a sua escolha.
8 |
9 | :::info
10 | Recomendo que você assista aos 2 vídeos que constam na documentação. São curtos e didáticos.
11 | :::
12 |
13 | Ao criarmos um widget extendendo um [InheritedWidget](https://api.flutter.dev/flutter/widgets/InheritedWidget-class.html), temos que sobrescrever os métodos **`of`** \(para acessar nosso widget facilmente\) e **`updateShouldNotify`** \(para indicar quando nosso widget deve ser reconstruído\).
14 |
15 | ```dart
16 | class MeuEmail extends InheritedWidget {
17 | const MeuEmail({
18 | Key key,
19 | @required this.provedor,
20 | @required Widget child,
21 | }) : assert(child != null),
22 | super(key: key, child: child);
23 |
24 | final String provedor;
25 |
26 | static MeuEmail of(BuildContext context) {
27 | return context.inheritFromWidgetOfExactType(MeuEmail) as MeuEmail;
28 | }
29 |
30 | @override
31 | bool updateShouldNotify(MeuEmail old) => provedor != old.provedor;
32 | }
33 | ```
34 |
35 | No exemplo acima, para acessar a propriedade provedor do widget **MeuEmail**, basta apenas invocar:
36 |
37 | ```dart
38 | final provedorEmail = MeuEmail.of(context).provedor;
39 | ```
40 |
41 | Simples, certo? Por isso o esta solução é utilizada \(e muito!\) pelo Flutter. Com ela, é possível acessar em qualquer lugar na _**widget tree**_ informações como o tamanho da tela e o tema da aplicação \(cores, tamanhos, fontes, etc\).
42 |
43 | :::caution
44 | **Inherited** significa _**herdado**_, sendo assim, todos os filhos de um **InheritedWidget** acessam suas propriedades facilmente \(eles herdam tais propriedade do "pai"\). Por isso o comum é colocar o InheritedWidget no topo da _**widget tree**_.
45 | :::
46 |
47 | Se necessário alterar a propriedade `provedor` do widget MeuEmail e refletir esta alteração por toda a estrutura de widget, devemos combinar os widgets [InheritedWidget](https://api.flutter.dev/flutter/widgets/InheritedWidget-class.html) e [InheritedModel](https://api.flutter.dev/flutter/widgets/InheritedModel-class.html).
48 |
49 | Como sugerido pelos vídeos da documentação, nesta situação o ideal é utilizar os packages como o [scoped\_model](https://pub.dev/packages/scoped_model) ou [provider](https://pub.dev/packages/provider). Eles irão prover este mesmo tipo de comportamento, com muito menos código.
--------------------------------------------------------------------------------
/docs/animacoes/explicitas.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 42
3 | ---
4 |
5 | # Explícitas
6 |
7 | É o mais poderoso tipo de animação com Flutter. Você tem o total controle sobre ela: iniciar, parar, repetir, reverter... não importa o "movimento".
8 |
9 | São úteis para criar animações complexas e personalizadas.
10 |
11 | :::tip Lembre-se
12 | Os comandos para da animação devem ser explícitos.
13 | :::
14 |
15 | Para ter todo este controle é necessário escrever mais código. Vamos lá!
16 |
17 | - Mixin necessário para acompanhar a passagem do tempo;
18 |
19 | ```dart
20 | extends State with SingleTickerProviderStateMixin
21 | ```
22 |
23 | - Crie a animação e um controlador para ela;
24 |
25 | ```dart
26 | late Animation animation;
27 | late AnimationController controller;
28 | ```
29 |
30 | - Inicialize a animação e o seu controlador. Neste caso, a animação muda o valor de 50 para 400 em 2 segundos;
31 |
32 | ```dart
33 | @override
34 | void initState() {
35 | super.initState();
36 | controller =
37 | AnimationController(duration: const Duration(seconds: 2), vsync: this);
38 | animation = Tween(begin: 50, end: 400).animate(controller);
39 | animation.addListener(() {
40 | setState(() {});
41 | });
42 | }
43 | ```
44 |
45 | - Através do controlador, é possível ter controle absoluto sobre a animação:
46 |
47 | ```dart
48 | controller.reset(); //reiniciar
49 | controller.repeat(); //repetir
50 | controller.forward(); //avançar
51 | controller.stop(); //parar
52 | ```
53 |
54 |
55 | - Criando um `Container` com animação explícita:
56 |
57 | ```dart
58 | @override
59 | Widget build(BuildContext context) {
60 | return Container(
61 | width: animation.value,
62 | height: 100,
63 | color: Colors.blue,
64 | );
65 | }
66 | ```
67 | - Lembre-se de liberar os recursos que foram alocados;
68 |
69 | ```dart
70 | @override
71 | void dispose() {
72 | controller.dispose();
73 | super.dispose();
74 | }
75 | ```
76 |
77 |
10 |
11 | Criando um MaterialApp;
12 |
13 | Escolhendo a paleta de cores `Colors.indigo`
14 |
15 | Atribuindo a sua `home` como sendo o widget `HomePage`
16 |
17 | Em HomePage, utilizando um Scaffold para aproveitar a sua estrutura
18 |
19 | Enquanto não implementamos o `body`, utilizamos o widget `Placeholder`
20 |
21 | Criamos uma lista de `Atracao`, que será exibida ao usuário
22 |
23 |
24 |
25 |
26 | ```dart
27 | import 'package:flutter/material.dart';
28 |
29 | void main() {
30 | runApp(const RockInRio());
31 | }
32 |
33 | class RockInRio extends StatelessWidget {
34 | const RockInRio({Key? key}) : super(key: key);
35 |
36 | @override
37 | Widget build(BuildContext context) {
38 | return MaterialApp(
39 | title: 'Rock in Rio',
40 | debugShowCheckedModeBanner: false,
41 | theme: ThemeData(primarySwatch: Colors.indigo),
42 | home: const HomePage(),
43 | );
44 | }
45 | }
46 |
47 | class HomePage extends StatefulWidget {
48 | const HomePage({Key? key}) : super(key: key);
49 |
50 | @override
51 | State createState() => _HomePageState();
52 | }
53 |
54 | class _HomePageState extends State {
55 | @override
56 | Widget build(BuildContext context) {
57 | return Scaffold(
58 | appBar: AppBar(
59 | title: const Text('Atrações'),
60 | ),
61 | body: const Placeholder(),
62 | );
63 | }
64 | }
65 |
66 | class Atracao {
67 | final String nome;
68 | final int dia;
69 | final List tags;
70 |
71 | const Atracao(this.nome, this.dia, this.tags);
72 | }
73 |
74 | const listaAtracoes = [
75 | Atracao("Iron Maiden", 2, ["Espetaculo", "Fas", "NovoAlbum"]),
76 | Atracao("Alok", 3, ["Influente", "Top", "Show"]),
77 | Atracao("Justin Bieber", 4, ["TopCharts", "Hits", "PríncipeDoPOP"]),
78 | Atracao("Guns N’ Roses", 8, ["Sucesso", "Espetáculo", "Fas"]),
79 | Atracao("Capital Inicial", 9, ["2019", "Novo Álbum", "Fas"]),
80 | Atracao("Green Day", 9, ["Sucesso", "Reconhecimento", "Show"]),
81 | Atracao("Cold Play", 10, ["NovoAlbum", "Sucesso", "2011"]),
82 | Atracao("Ivete Sangalo", 10, ["Unica", "Carreiras", "Fas"]),
83 | Atracao("Racionais", 3, ["Hits", "Prêmios", "Respeito"]),
84 | Atracao("Gloria Groove", 8, ["Streams", "Representatividade", "Sucesso"]),
85 | Atracao("Avril Lavigne", 9, ["Estreia", "Sucesso", "Lançamento"]),
86 | Atracao("Ludmilla", 10, ["Representativade", "Sucesso", "Parcerias"]),
87 | ];
88 | ```
--------------------------------------------------------------------------------
/blog/2022-05-11-ciclo-de-vida.md:
--------------------------------------------------------------------------------
1 | ---
2 | slug: ciclo-de-vida
3 | title: Ciclo de vida
4 | authors: rubensdemelo
5 | tags: [flutter, stateless, stateful, tutorial, ciclo-de-vida]
6 | ---
7 |
8 | Neste post, vamos explorar um dos conceitos mais importantes para quem está começando com Flutter: o ciclo de vida dos widgets.
9 |
10 | Voçe já deve saber que em Flutter, tudo é um widget e que temos 2 tipos: Stateless e o Stateful.
11 |
12 | E a diferença entre eles é o objeto State, pois ele confere ao Stateful o poder da mutação enquanto o Stateless permanece imutável.
13 |
14 | O construtor destes widgets tem a mesma estrutura:
15 |
16 | ```dart
17 | class GreenFrog extends StatelessWidget {
18 | const GreenFrog({ Key? key }) : super(key: key);
19 |
20 | @override
21 | Widget build(BuildContext context) {
22 | return Container(color: const Color(0xFF2DBD3A));
23 | }
24 | }
25 | ```
26 |
27 | ```dart
28 | class YellowBird extends StatefulWidget {
29 | const YellowBird({ Key? key }) : super(key: key);
30 |
31 | @override
32 | State createState() => _YellowBirdState();
33 | }
34 | ```
35 |
36 | Ambos aos serem implementados, fazem override diferentes: método `build` no Stateless e o Stateful faz do `createState()`, nos obrigando à implementar `_YellowBirdState()`.
37 |
38 | E nele nós temos o seguinte código:
39 |
40 | ```dart
41 | class _YellowBirdState extends State {
42 | @override
43 | Widget build(BuildContext context) {
44 | return Container(color: const Color(0xFFFFE306));
45 | }
46 | }
47 | ```
48 |
49 | E é aqui que a mágica acontece. Graças ao objeto `State`, podemos mudar a cor do Container de amarelo para vermelha, usando o `setState()`. Algo impossível de se fazer em no GreenFrog, que possui a cor verde e por ser um Stateless widget, é imutável.
50 |
51 | Até aqui deduzimos então que:
52 |
53 | :::tip
54 |
55 | **Stateless** e **Stateful** widgets possuem o mesmo ciclo de vida. Quando o construtor é invocado, eles executam o mesmo override.
56 |
57 | :::
58 |
59 | E como vimos anteriormente, o Stateful possui o override ao método `createState()` e que o retorno é um objeto State.
60 |
61 | E é exatamente aqui que aprofundamos quando se trata do “ciclo de vida dos widgets”.
62 |
63 | Sendo bem rigorosos, podemos afirmar que o “ciclo de vida”, portanto, trata-se do objeto State e não do Stateless/Stateful.
64 |
65 | Sendo menos rigorosos, podemos afirmar que o “ciclo de vida” de um Stateful é mais amplo, pois envolve também o objeto `State`, afinal, não é possível criar um Stateful sem ter um objeto State.
66 |
67 | No próximo post, iremos abordar os métodos o `initState` e o `dispose`, pois são eles que acompanham a criação e destruição do objeto State (do Stateful widget).
--------------------------------------------------------------------------------
/static/img/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
71 |
--------------------------------------------------------------------------------
/blog/2022-03-26-declarativo-imperativo.md:
--------------------------------------------------------------------------------
1 | ---
2 | slug: declarativo-imperativo
3 | title: Imperativo X Declarativo
4 | authors: rubensdemelo
5 | tags: [flutter, imperativo, declarativo]
6 | ---
7 |
8 | :::info Resumão:
9 | Imperativa: especificar como resolver um problema; controle detalhado.
10 |
11 | Declarativa: concentra-se no que o código deve realizar; concentrar no resultado.
12 |
13 | Essas duas abordagens são comumente usadas na programação e é importante entender suas diferenças para compreender melhor o uso [declarativo pelo Flutter](https://docs.flutter.dev/get-started/flutter-for/declarative).
14 |
15 | Compreender a diferença, facilita o entendimento em como o Flutter constroi interfaces.
16 | :::
17 |
18 |
19 |
20 | ## Imperativa
21 |
22 | É um processo passo a passo que diz ao computador o que fazer e como fazê-lo. Em outras palavras, é um conjunto de instruções que o computador segue para alcançar o resultado desejado.
23 |
24 | A programação imperativa envolve escrever código que especifique exatamente como resolver um problema. Ela é baseada no controle do fluxo de execução usando declarações como loops, condicionais e variáveis. Lembre-se: **passo-a-passo**.
25 |
26 | Adequada para situações em que você precisa ter mais controle sobre o fluxo do programa. Isso significa que se você precisa fazer algo muito específico e precisa ter certeza de que é feito de uma maneira determinada, então a abordagem imperativa pode ser a melhor.
27 |
28 | ## Declarativa
29 |
30 | É baseada em descrever o resultado desejado sem especificar como alcançá-lo. Em vez de escrever código que especifica como resolver um problema, a programação declarativa se concentra no que o código deve realizar.
31 |
32 | A programação declarativa envolve escrever código que descreve o problema e o resultado desejado, sem especificar como chegar lá. É baseado na definição de regras e relacionamentos entre elementos. Lembre-se: **resultado-desejado**.
33 |
34 | Adequada para situações em que você deseja descrever o que deseja alcançar, sem se preocupar em como chegar lá. Isso significa que se você deseja se concentrar no resultado, e não no processo.
35 |
36 | Ao trabalhar com interfaces de usuário, usar a abordagem declarativa para garantir que a interface pareça e se comporte exatamente como você deseja, sem se preocupar com a forma como é implementada.
37 |
38 | ## Na prática
39 |
40 | SQL: Declarativo. Declaramos o resultado ao banco de dados: inserir, atualizar, excluir, consultar... mas nós não o instruimos em como ele deve executar tais operações.
41 |
42 | Algorítimo: Imperativo. Imposto a cada linha de código como ele deve se comportar. Declarar variável, computar valores, avaliar expressões. Estamos instruindo exatamente o comportamento que queremos que o programa tenha.
43 |
44 | ## Flutter
45 |
46 | Como mecionado anteriormente, o Flutter utiliza a abordagem declarativa: **resultado**.
47 |
48 | Ao construi interfaces com ele, declaramos algo como: 1 imagem, 2 campos de texto e um botão.
49 |
50 | E o framework se encarrega de todo o resto, sem se preocupar com a implementação de cada elemento.
51 |
52 | Com isso, os desenvolvedores podem se concentrar no que desejam alcançar e deixar que o framework se encarregue de como implementá-lo.
53 |
54 | #### Até breve
55 |
--------------------------------------------------------------------------------
/docs/15-ciclo-de-vida.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 15
3 | ---
4 |
5 | # State
6 |
7 | Vamos analisar com calma o ciclo de vida de um objeto [State](https://api.flutter.dev/flutter/widgets/State-class.html).
8 |
9 | 
10 |
11 | Pode parecer complicado, porém é mais simples do que você imagina. Todo este ciclo é necessário para que o método [setState()](https://api.flutter.dev/flutter/widgets/State/setState.html) cumpra o seu papel, que é notificar nosso widget que ele precisa ser reconstruído (ter seu método [build()](https://api.flutter.dev/flutter/widgets/State/build.html) executado novamente).
12 |
13 | import Tabs from '@theme/Tabs';
14 | import TabItem from '@theme/TabItem';
15 |
16 |
17 |
18 |
19 | [initState](https://api.flutter.dev/flutter/widgets/State/initState.html): Chamado **apenas 1 única vez**, na criação no widget**.** Quando o widget é **inserido** na _widget tree_.
20 |
21 |
22 |
23 |
24 | [build](https://api.flutter.dev/flutter/widgets/State/build.html): Chamado em diferentes situações. Sempre que o widget precisar ser reconstruído ou após o [initState()](https://api.flutter.dev/flutter/widgets/State/initState.html) ou após a função[ setState()](https://api.flutter.dev/flutter/widgets/State/setState.html) e até mesmo quando o widget for [removido](https://api.flutter.dev/flutter/widgets/State/deactivate.html) da widget tree para ser inserido em outro ponto (isto ficará mais claro quando construirmos nosso primeiro app).
25 |
26 |
27 |
28 |
29 | [dispose](https://api.flutter.dev/flutter/widgets/State/dispose.html): Chamado quando o widget for **removido** da widget tree **permanentemente**.
30 |
31 |
32 |
33 |
34 | [setState](https://api.flutter.dev/flutter/widgets/State/setState.html): Responsável por notificar nosso widget que o estado interno foi alterado. Por exemplo, ao concluir uma requisição HTTP, queremos exibir estas informações na tela. Para isso, preenchemos nossa tela com as informações recebidas e invocamos a função [setState()](https://api.flutter.dev/flutter/widgets/State/setState.html).
35 |
36 |
37 |
38 |
39 | [didUpdateWidget](https://api.flutter.dev/flutter/widgets/State/didUpdateWidget.html): Sempre que o seu widget sofrer alterações, este método é chamado e executado antes do [build()](https://api.flutter.dev/flutter/widgets/State/build.html). Ou seja, sempre que chamar o [setState()](https://api.flutter.dev/flutter/widgets/State/setState.html), este método é executado. Pode ser útil ao lidar com animações e/ou quando precisar ter acesso ao estado antigo do widget.
40 |
41 |
42 |
43 |
44 | :::tipo
45 | Cada um dos métodos acima são executados em momentos diferentes. Cada um deles possui responsabilidades e comportamentos diferentes, logo, devemos utilizá-los da maneira correta.
46 | :::
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/blog/2022-12-14-escolher-gerenciamento-estado.md:
--------------------------------------------------------------------------------
1 | ---
2 | slug: escolhendo-gerenciamento-estado
3 | title: Escolhendo o gerenciamento de estado
4 | authors: rubensdemelo
5 | tags: [flutter, gerenciamento-estado]
6 | ---
7 |
8 | :::info Resumão:
9 |
10 | Flutter é um framework não-opinativo.
11 |
12 | Responsabilidade e discernimento na escolha.
13 |
14 | Mantenha o mais simples possível
15 | :::
16 |
17 | O Flutter é um framework não opinativo, ou seja, ele não impõe e não obriga sobre como funcionalidades devem ser implementadas.
18 |
19 | Permite que os desenvolvedores usem a sua criatividade e experiência para encontrar soluções personalizadas para seus problemas, em vez de serem forçados a seguir um conjunto rígido de regras e convenções impostas pelo framework.
20 |
21 | Isso significa que é possível escolher diferentes opções que resolvem o mesmo problema.
22 |
23 | Consumir uma API REST, utilizando o package [http](https://pub.dev/packages/http), [dio](https://pub.dev/packages/dio) ou [chopper](https://pub.dev/packages/chopper) ?.
24 |
25 | Navegação utilizando APIs nativas ou packages como [fluro](https://pub.dev/packages/fluro), [beamer](https://pub.dev/packages/beamer) ou [go_router](https://pub.dev/packages/go_router) ?.
26 |
27 | Armazenamento local, com [sqflite](https://pub.dev/packages/sqflite), [drift](https://pub.dev/packages/drift) ou [isar](https://pub.dev/packages/isar) ?.
28 |
29 | Cada uma das opções possuem prós e contras.
30 |
31 | No gerenciamento de estado, a mesma coisa.
32 |
33 | Sobram alternativas nativas: [setState()](https://api.flutter.dev/flutter/widgets/State/setState.html), [ChangeNotifier](https://api.flutter.dev/flutter/foundation/ChangeNotifier-class.html), [InheritedWidget](https://api.flutter.dev/flutter/widgets/InheritedWidget-class.html), [StreamBuilder](https://api.flutter.dev/flutter/widgets/StreamBuilder-class.html), etc.
34 |
35 | E packages, como [riverpod](https://pub.dev/packages/riverpod), [flutter_bloc](https://pub.dev/packages/flutter_bloc), [provider](https://pub.dev/packages/provider), [mobx](https://pub.dev/packages/mobx), etc.
36 |
37 | Mas qual o motivo então de discussões acaloradas sobre a "melhor" alternativa para gerenciamento de estado ?
38 |
39 | O motivo é simples: não existe "bala de prata", ou seja, não existe a melhor opção. E sim, aquela opção que se encaixa melhor no seu projeto.
40 |
41 | Cabe aos desenvolvedores a responsabilidade e o discernimento na escolha.
42 |
43 | É natural que as pessoas discutam sobre como fazer isso da “melhor” maneira possível. E cada um vai defender a sua escolha em detrimento das outras.
44 |
45 | Felizmente, o amadurecimento do Flutter e da comunidade contribuíram para que estas discussões tivessem cada vez **menos importância**. Mas ainda assim continua sendo um tópico “quente”.
46 |
47 | O Flutter é um framework que oferece flexibilidade e liberdade de escolha em suas implementações.
48 |
49 | E como mencionado anteriormente, **não existe** a “melhor” maneira. A escolha da opção de gerenciamento de estado ideal depende do projeto e do **contexto** em que está sendo usada.
50 |
51 | E para finalizar e responder a pergunta deste post, aqui está a resposta:
52 |
53 | - Avalie se as alternativas nativas são suficientes
54 | - Se optar por packages, considere a complexidade do estado no aplicativo. Avalie a documentação e repositório. Avalie mais de um package.
55 | - Faça uma prova de conceito com a situação mais complexa possível.
56 |
57 | Regra de ouro: mantenha o mais simples possível.
--------------------------------------------------------------------------------
/docs/interface/cupertino.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 3
3 | ---
4 |
5 | # Cupertino
6 |
7 | Na biblioteca [Cupertino](https://api.flutter.dev/flutter/cupertino/cupertino-library.html) temos o duas opções de widget para estruturar a tela do aplicativo;
8 |
9 | [CupertinoPageScaffold](https://api.flutter.dev/flutter/cupertino/CupertinoPageScaffold-class.html): Onde temos uma barra de navegação no topo \(onde utilizamos uma [CupertinoNavigationBar](https://api.flutter.dev/flutter/cupertino/CupertinoNavigationBar-class.html) e o restante da tela é com o conteúdo.
10 |
11 | [CupertinoTabScaffold](https://api.flutter.dev/flutter/cupertino/CupertinoTabScaffold-class.html): Similar ao widget anterior, porém além da barra de navegação superior, este fornece um layout que possui uma barra de navegação inferior, onde utilizando uma [CupertinoTabBar](https://api.flutter.dev/flutter/cupertino/CupertinoTabBar-class.html) e [CupertinoTabView](https://api.flutter.dev/flutter/cupertino/CupertinoTabView-class.html).
12 |
13 | Outros componentes característicos de um aplicativo iOS nativo também estão disponíveis, como:
14 |
15 | [CupertinoActionSheet](https://api.flutter.dev/flutter/cupertino/CupertinoActionSheet-class.html): Quando precisarmos oferecer opções de escolha para alguma ação.
16 |
17 | [CupertinoSegmentedControl](https://api.flutter.dev/flutter/cupertino/CupertinoSegmentedControl-class.html): Utilizado para navegação por abas.
18 |
19 | [CupertinoPicker](https://api.flutter.dev/flutter/cupertino/CupertinoPicker-class.html), [CupertinoDatePicker](https://api.flutter.dev/flutter/cupertino/CupertinoDatePicker-class.html) e [CupertinoTimerPicker](https://api.flutter.dev/flutter/cupertino/CupertinoTimerPicker-class.html): Para facilitar a entrada de dados pelo usuário.
20 |
21 | Veja o código de um aplicativo combinando alguns destes widgets:
22 |
23 | ```dart
24 | import 'package:flutter/cupertino.dart';
25 |
26 | void main() => runApp(MeuCupertinoApp());
27 |
28 | class MeuCupertinoApp extends StatelessWidget {
29 | @override
30 | Widget build(BuildContext context) {
31 | return CupertinoApp(
32 | title: 'Cupertino App',
33 | home: CupertinoTabScaffold(
34 | tabBar: CupertinoTabBar(items: const [
35 | BottomNavigationBarItem(
36 | icon: Icon(CupertinoIcons.home), label: 'Home'),
37 | BottomNavigationBarItem(
38 | icon: Icon(CupertinoIcons.settings), label:'Settings'),
39 | ]),
40 | tabBuilder: (context, index) {
41 | return const Center(child: Text('Hello World'));
42 | },
43 | ),
44 | );
45 | }
46 | }
47 |
48 | ```
49 |
50 |
51 |
52 |
57 |
58 | Neste vídeo, os widget da biblioteca [Cupertino](https://api.flutter.dev/flutter/cupertino/cupertino-library.html) são apresentados com maiores detalhes.
59 |
60 |
61 |
--------------------------------------------------------------------------------
/docs/2-widgets.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 2
3 | description: Tudo no Flutter é um widget
4 | ---
5 |
6 | # Widgets
7 |
8 | Todo aplicativo Flutter é um widget. Composto de outra centenas de widgets. Portanto, entende-los é mais do que a nossa obrigação. Uma coisa bacana, é que na própria documentação do Flutter, eles deixam claro que a inspiração para os widgets vieram do [React](https://pt-br.reactjs.org/). Assim como no framework do Facebook, todo aplicativo é baseado em componentes, no Flutter todo aplicativo é baseado em widgets.
9 |
10 | _**"A ideia central é que você construa sua interface com widgets"**_
11 |
12 | 
13 |
14 | :::tip Lego
15 | Pense no aplicativo como um LEGO, onde cada pequeno widget representa uma peça e ao final, várias peças compõem um brinquedo.
16 |
17 | No Flutter, vários widgets são combinados para compor um aplicativo.
18 | :::
19 |
20 | Existem apenas 2 tipos de widgets: [Stateless ](https://api.flutter.dev/flutter/widgets/StatelessWidget-class.html)e [Stateful](https://api.flutter.dev/flutter/widgets/StatefulWidget-class.html). Iremos abordar esta diferença na próxima seção.
21 |
22 | Podemos classificar os widgets em 2 grupos principais: **Layout** e **UI \(user interface\)**.
23 |
24 | :::info
25 | Certamente temos outros widgets que não se enquadram perfeitamente em nenhum destes grupos, mas com essa divisão, fica fácil de identificar quando e quais widgets utilizar para construir uma interface.
26 | :::
27 |
28 | Widgets de **layout**, são aqueles que se preocupam apenas em posicionar outros widgets. Alguns dos principais:
29 |
30 | * [Column](https://api.flutter.dev/flutter/widgets/Column-class.html)
31 | * [Row](https://api.flutter.dev/flutter/widgets/Row-class.html)
32 | * [Scaffold](https://api.flutter.dev/flutter/material/Scaffold-class.html)
33 | * [Stack](https://api.flutter.dev/flutter/widgets/Stack-class.html)
34 |
35 | Widgets de **interface**, são aqueles que efetivamente estão visíveis ao usuário, como:
36 |
37 | * [Text](https://api.flutter.dev/flutter/widgets/Text-class.html)
38 | * [RaisedButton](https://api.flutter.dev/flutter/material/RaisedButton-class.html)
39 | * [Switch](https://api.flutter.dev/flutter/material/Switch-class.html)
40 |
41 | :::info
42 | No [catálogo](https://flutter.dev/docs/development/ui/widgets), temos mais de 205 widgets documentados \(vale a pena dar uma conferida\).
43 | :::
44 |
45 | Precisamos dar destaque para 2 conjuntos de widgets amplamente utilizados e que já abordei na seção Visão Geral, o primeiro e mais popular é o [Material](https://flutter.dev/docs/development/ui/widgets/material) package, que segue as definições de layout do Material Design e o [Cupertino](https://flutter.dev/docs/development/ui/widgets/cupertino) package, seguindo as definições de design do iOS.
46 |
47 | Ambos pacotes nos fornecem widgets _**ready-to-use**_**,** bastando importá-los no nosso projeto e utilizar. O time do Flutter é responsável pela construção e manutenção de cada um deles. Caso tenham mudanças ou novos componentes para as plataformas, será questão de tempo até serem implementados pelo Flutter.
48 |
49 | Nada nos impede de criarmos um app com a "cara" do iOS para Android e vice-versa. Também não significa que nosso aplicativo sempre terá uma aparência _ios-style_ ou _android-style_, muito pelo contrário. Flutter nos proporciona níveis incríveis de personalização.
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/docs/animacoes/implicitas.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 41
3 | ---
4 |
5 | # Implícitas
6 |
7 | Para mostrar o quão simples é criar uma animação com Flutter, vamos direto para o código:
8 |
9 | Vamos criar nosso **"ContainerDesanimado"**:
10 |
11 | ```dart
12 | Container(
13 | width: 150, height: 150,
14 | color: cor //variável para armazenar a cor
15 | )
16 | ```
17 |
18 | Ao clicarmos no botão, a nova cor passa a ser amarelo.
19 |
20 | :::info
21 | O método **`setState`** é invocado e a variável **`cor`** recebe o novo valor.
22 | :::
23 |
24 |
29 |
30 | Sem graça, não é? Vamos animá-lo! Para isso, é só substituir o Container por um [AnimatedContainer](https://api.flutter.dev/flutter/widgets/AnimatedContainer-class.html):
31 |
32 | ```dart
33 | AnimatedContainer(
34 | duration: Duration(seconds: 1),
35 | width: 150, height: 150,
36 | color: cor
37 | )
38 | ```
39 |
40 | Só precisamos adicionar o parametro `duration`, para indicar quanto em tempo a mudança de cor irá acontecer. Neste caso, 1 segundo.
41 |
42 |
47 |
48 | Muito simples, certo ?! E o melhor de tudo é que o Flutter já nos oferece vários widgets **"Animated"**:
49 |
50 | Alinhamento: [AnimatedAlign](https://api.flutter.dev/flutter/widgets/AnimatedAlign-class.html)
51 |
52 | Opacidade: [AnimatedOpacity](https://api.flutter.dev/flutter/widgets/AnimatedOpacity-class.html)
53 |
54 | Padding: [AnimatedPadding](https://api.flutter.dev/flutter/widgets/AnimatedPadding-class.html)
55 |
56 | Escala: [AnimatedScale](https://api.flutter.dev/flutter/widgets/AnimatedScale-class.html)
57 |
58 | Todos os widgets **animated** derivam de um [ImplicityAnimatedWidget](https://api.flutter.dev/flutter/widgets/ImplicitlyAnimatedWidget-class.html). Nela, é possível ver todos os widgets disponíveis \(ou seja, widget que implementam esta classe\).
59 |
60 |
61 | Percebeu que o Flutter se encarregou de executar a animação, após invocarmos o **`setState()`** ? Tivemos pouco ou nenhum controle sobre ela, apenas delegamos a tarefa de animar o container da cor vermelha para amarela.
62 |
63 | A facilidade de implementar este tipo de animação, justifica a ausência de controle. É possível melhorar a experiência do usuário com widgets animados em poucas linhas de código, como vimos acima.
64 |
65 | E mesmo que precise controlar cada detalhe de uma animação, temos as animações explícitas disponíveis.
66 |
67 |
68 |
69 |
70 |
71 |
72 | Confira este vídeo:
73 |
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/blog/2022-05-17-flutter-3.md:
--------------------------------------------------------------------------------
1 | ---
2 | slug: flutter-3
3 | title: Flutter 3
4 | authors: rubensdemelo
5 | tags: [flutter, material3, firebase, games]
6 | ---
7 |
8 | ## Youtube
9 |
10 | Para complementar este post, também há o vídeo no youtube.
11 |
12 |
13 |
14 |
15 | ## Novidades
16 |
17 | A versão 3 do Flutter foi apresentado no Google I/O de 2022.
18 |
19 | O grande destaque desta nova versão é que o framework está com suporte estável para macOS e Linux, atingindo 6 plataformas diferentes à partir da mesma codebase.
20 |
21 | Outras 3 funcionalidade que chamaram a atenção foram:
22 |
23 | ### Material 3
24 |
25 | A nova geracao do Material Design está progressivamente sendo implementada, trazendo um novo esquema de cores, melhorias na tipografia novos componentes e uma capacidade muito maior na personalizacão dos aplicativos. Acompanhe a issue e fique por dentro das atualizacões.
26 |
27 | https://github.com/flutter/flutter/issues/91605
28 |
29 | ---
30 |
31 | ### Firebase Crashlytics
32 |
33 | Agora é possível acessar em tempo real os relatórios de "crash" (com stacktrace completo) do seu aplicativo, algo antes exclusivo aos apps nativos. Vale ressalver que este recurso do Firebase é gratuito.
34 |
35 | ---
36 |
37 | ### Flutter Web
38 |
39 | Utilizando a API ImageDecoder (nos browsers que oferecem suporte) a decodificaćão de imagens ficou 2x mais rápida. E a nova API do Flutter que controla o ciclo de vida de um aplicativo agora fornece um controle maior da inicializaćão. Confira os detalhes no link
40 |
41 | https://docs.flutter.dev/development/platform-integration/web/initialization
42 |
43 | ---
44 |
45 | ### Performance
46 |
47 | Como de costume, toda atualizacão do traz consigo melhorias em performance e desta vez não foi diferente. Basta atualizar a versão e executar o seu aplicativo.
48 |
49 | ---
50 |
51 | ### Casual Games Toolkit
52 |
53 | Um outra novidade que deixou muita gente empolgada é o . Um conjunto recursos para criar jogos casuais utilizando Flutter.
54 |
55 | https://flutter.dev/games
56 |
57 | ---
58 |
59 | ## Dart 2.17
60 | A nova versão da linguagem Dart foi anunciada, trazendo como grandes novidades:
61 |
62 | ### Enums
63 |
64 | Agora é possível adicionar propriedades/métodos à um Enum.
65 | ```dart
66 | enum FlutterBootcamp {
67 | kura('setState'),
68 | libria('testes'),
69 | civitas('firebase');
70 |
71 | final String conteudo;
72 |
73 | const FlutterBootcamp(this.conteudo);
74 |
75 | String exibirConteudo() {
76 | return 'O principal conteúdo deste app é: $conteudo';
77 | }
78 | }
79 |
80 | void main() => print(FlutterBootcamp.civitas.exibirConteudo());
81 | ```
82 |
83 | ### Super initializers
84 |
85 | A passagem de parametro para "super-classe" (ou classe mãe) ficou mais simples:
86 |
87 | ```dart
88 | class Bootcamp {
89 | String? linguagem;
90 | Bootcamp({this.linguagem});
91 | ...
92 | }
93 |
94 | // Antes
95 | class FlutterBootcamp extends Bootcamp {
96 | FlutterBootcamp({String? linguagem}) : super(linguagem: linguagem);
97 | }
98 |
99 | // Depois
100 | class FlutterBootcamp extends Bootcamp {
101 | FlutterBootcamp({super.linguagem});
102 | }
103 | ```
104 |
105 | ### Named args
106 |
107 | Os named arguments podem ser informados em qualquer ordem. Não precisam ser declarados no final do construtor.
108 |
109 | ```dart
110 | class FlutterBootcamp {
111 | final String? conteudo;
112 | final int? aplicativos;
113 |
114 | const FlutterBootcamp(this.conteudo, {this.aplicativos});
115 | }
116 |
117 | // antes
118 | FlutterBootcamp('Do básico ao avançado', aplicativos: 6);
119 |
120 | // depois
121 | FlutterBootcamp(aplicativos: 6, 'Do básico ao avançado');
122 | ```
--------------------------------------------------------------------------------
/docs/interface/material.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 2
3 | ---
4 |
5 | # Material
6 |
7 | No [catálogo](https://flutter.dev/docs/development/ui/widgets/material) de widgets do Flutter, atualmente conta com quase 40 widgets prontos para uso. Desde um simples [botão](https://api.flutter.dev/flutter/material/RaisedButton-class.html) até widgets para estruturar todo o aplicativo, como o [Scaffold](https://api.flutter.dev/flutter/material/Scaffold-class.html).
8 |
9 | Navegando pelo catálogo, é possível identificar o que cada widget representa, porém listarei aqui os principais:
10 |
11 | [MaterialApp](https://api.flutter.dev/flutter/material/MaterialApp-class.html): Fornece a estrutura completa para um aplicativo, de acordo com o Material Design. Todas as rotas/navegações são gerenciadas por ele. A estilização (tema / cores / fontes / textos, etc) podem (e devem) ser definidos aqui. A ii18n(internacionalização) do aplicativo também é configurada neste widget. Ele será o widget raiz de um aplicativo.
12 |
13 | [Scaffold](https://api.flutter.dev/flutter/material/Scaffold-class.html): Para estruturar o layout de uma tela, este é o widget ideal. Neste podemos adicionar barras de navegação \(superior e inferior\), e na propriedade **body**, definimos o principal widget da nossa tela.
14 |
15 | [BottomNavigationBar](https://api.flutter.dev/flutter/material/BottomNavigationBar-class.html): Barra de navegação inferior, onde podemos adicionar ícones e textos das nossas telas.
16 |
17 | [AppBar](https://api.flutter.dev/flutter/material/AppBar-class.html): Barra superior, onde podemos colocar o título da nossa tela. O Flutter também utiliza este widget para exibir o ícone
18 |
19 | [Drawer](https://api.flutter.dev/flutter/material/Drawer-class.html): Menu lateral, que se abre após clicarmos em um ícone na [AppBar](https://api.flutter.dev/flutter/material/AppBar-class.html). Ao adicionarmos um [Drawer](https://api.flutter.dev/flutter/material/Drawer-class.html) ao [Scaffold](https://api.flutter.dev/flutter/material/Scaffold-class.html) e não adicionarmos uma [AppBar](https://api.flutter.dev/flutter/material/AppBar-class.html), o ícone para abrir o [Drawer](https://api.flutter.dev/flutter/material/Drawer-class.html) não é exibido.
20 |
21 | Veja o código de um aplicativo combinando todos estes widgets:
22 |
23 | ```dart
24 | import 'package:flutter/material.dart';
25 |
26 | void main() => runApp(MeuMaterialApp());
27 |
28 | class MeuMaterialApp extends StatelessWidget {
29 | @override
30 | Widget build(BuildContext context) {
31 | return MaterialApp(
32 | home: Scaffold(
33 | appBar: AppBar(
34 | title: const Text('App Bar'),
35 | ),
36 | drawer: const Drawer(),
37 | body: const Center(
38 | child: Text('Hello World'),
39 | ),
40 | bottomNavigationBar: BottomNavigationBar(
41 | items: const [
42 | BottomNavigationBarItem(
43 | icon: Icon(Icons.home),
44 | label: 'Home',
45 | ),
46 | BottomNavigationBarItem(
47 | icon: Icon(Icons.settings),
48 | label: 'Settings',
49 | )
50 | ],
51 | ),
52 | ),
53 | );
54 | }
55 | }
56 |
57 | ```
58 |
59 |
64 |
65 | Neste vídeo, há uma demonstração de como utilizar os widgets da biblioteca [Material](https://api.flutter.dev/flutter/material/material-library.html) para construir um aplicativo com pouco mais de 100 linhas de código.
66 |
67 |
68 |
--------------------------------------------------------------------------------
/docs/3-dart.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 3
3 | description: 'Entender a arquitetura do Flutter é importante, precisamos entender toda a "anatomia" dos nossos aplicativos.'
4 | ---
5 |
6 | # DART
7 |
8 | É a linguagem de programação criada pelo Google e utilizada para escrever o Flutter.
9 |
10 | Graças ao DART, o Flutter se torna um framework único, tanto para o desenvolvedor quanto para o usuário final. O desenvolvedor tem uma incrível experiência e o usuário final tem um aplicativo nativo, de alta performance.
11 |
12 | Caso você já possua experiência com qualquer linguagem _C-style_, irá perceber que Dart é muito amigável e não terá dificuldades em aprendê-la:
13 |
14 | - Tipada, porém isto é opcional.
15 | - Moderna (generics\, funções, interfaces e mixins).
16 | - High Order Functions ( forEach(), map(), etc ).
17 | - Utiliza sintaxe _C-style_ (como C#, Javascript).
18 | - Pode ser compilada e interpretada. _\*\*_
19 |
20 | Tipos suportados:
21 |
22 | - numbers
23 | - strings
24 | - boolean
25 | - collections (list, set, map)
26 | - rune ( representar UNICODE caracteres como string)
27 | - symbols
28 |
29 | Este [guia](https://dart.dev/guides/language/language-tour) te ajudará a se familiarizar com a linguagem antes de aprender o framework.
30 |
31 | O conhecimento básico proporcionado pelo guia, é suficiente para dar os primeiros passos e sentir a deliciosa experiência de construir um aplicativo Flutter.
32 |
33 | **Este vídeo aborda alguns detalhes da linguagem:**
34 |
35 |
36 |
37 |
38 |
39 | ---
40 |
41 | ### dartpad.dev
42 |
43 | É um IDE online para Dart e Flutter, permitindo que você escreva, execute e compartilhe códigos diretamente em um browser.
44 |
45 | Ideal para aprender, afinal, o resultado da execução do código é instantâneo.
46 |
47 | Acelera a prototipação, pois não requer configuração ou instalação.
48 |
49 | Facilita o compartilhamento, basta criar um Github Gist com o link do dartpad.dev.
50 |
51 | [dartpad.dev](http://dartpad.dev/)
52 |
53 | 
54 |
55 | #### Este vídeo explora o poder do `dartpad.dev`:
56 |
57 |
--------------------------------------------------------------------------------
/static/img/declarative.excalidraw:
--------------------------------------------------------------------------------
1 | {
2 | "type": "excalidraw",
3 | "version": 2,
4 | "source": "https://excalidraw.com",
5 | "elements": [
6 | {
7 | "id": "XbPPcAQ_9xkizvw42zwfp",
8 | "type": "text",
9 | "x": 920,
10 | "y": 326.0465326821486,
11 | "width": 48.752788644215975,
12 | "height": 48.752788644215975,
13 | "angle": 0,
14 | "strokeColor": "#c92a2a",
15 | "backgroundColor": "transparent",
16 | "fillStyle": "hachure",
17 | "strokeWidth": 1,
18 | "strokeStyle": "solid",
19 | "roughness": 1,
20 | "opacity": 100,
21 | "groupIds": [],
22 | "strokeSharpness": "sharp",
23 | "seed": 1988602232,
24 | "version": 257,
25 | "versionNonce": 659189256,
26 | "isDeleted": false,
27 | "boundElements": null,
28 | "updated": 1646486544018,
29 | "link": null,
30 | "text": "UI",
31 | "fontSize": 40.81628816725058,
32 | "fontFamily": 3,
33 | "textAlign": "left",
34 | "verticalAlign": "top",
35 | "baseline": 38.752788644215975,
36 | "containerId": null,
37 | "originalText": "UI"
38 | },
39 | {
40 | "id": "ioT-QZ3X5vU_r4D5vlo9d",
41 | "type": "text",
42 | "x": 975.4137801159534,
43 | "y": 326.329979127755,
44 | "width": 24.943287213319802,
45 | "height": 48.752788644215975,
46 | "angle": 0,
47 | "strokeColor": "#495057",
48 | "backgroundColor": "transparent",
49 | "fillStyle": "hachure",
50 | "strokeWidth": 1,
51 | "strokeStyle": "solid",
52 | "roughness": 1,
53 | "opacity": 100,
54 | "groupIds": [],
55 | "strokeSharpness": "sharp",
56 | "seed": 513036152,
57 | "version": 137,
58 | "versionNonce": 459363960,
59 | "isDeleted": false,
60 | "boundElements": null,
61 | "updated": 1646486544018,
62 | "link": null,
63 | "text": "=",
64 | "fontSize": 40.81628816725059,
65 | "fontFamily": 3,
66 | "textAlign": "left",
67 | "verticalAlign": "top",
68 | "baseline": 38.752788644215975,
69 | "containerId": null,
70 | "originalText": "="
71 | },
72 | {
73 | "id": "gdwf7GAZV4zl387le42js",
74 | "type": "text",
75 | "x": 1011.8366483763148,
76 | "y": 327.74721135578363,
77 | "width": 24.943287213319802,
78 | "height": 48.752788644215975,
79 | "angle": 0,
80 | "strokeColor": "#364fc7",
81 | "backgroundColor": "transparent",
82 | "fillStyle": "hachure",
83 | "strokeWidth": 1,
84 | "strokeStyle": "solid",
85 | "roughness": 1,
86 | "opacity": 100,
87 | "groupIds": [],
88 | "strokeSharpness": "sharp",
89 | "seed": 250663288,
90 | "version": 129,
91 | "versionNonce": 1189047560,
92 | "isDeleted": false,
93 | "boundElements": null,
94 | "updated": 1646486544018,
95 | "link": null,
96 | "text": "f",
97 | "fontSize": 40.81628816725059,
98 | "fontFamily": 3,
99 | "textAlign": "left",
100 | "verticalAlign": "top",
101 | "baseline": 38.752788644215975,
102 | "containerId": null,
103 | "originalText": "f"
104 | },
105 | {
106 | "id": "9qLIs2pIhZHIv6Uwwn9oX",
107 | "type": "text",
108 | "x": 1039.4726768228888,
109 | "y": 325.1961933453317,
110 | "width": 120.18129293690453,
111 | "height": 48.752788644215975,
112 | "angle": 0,
113 | "strokeColor": "#2b8a3e",
114 | "backgroundColor": "transparent",
115 | "fillStyle": "hachure",
116 | "strokeWidth": 1,
117 | "strokeStyle": "solid",
118 | "roughness": 1,
119 | "opacity": 100,
120 | "groupIds": [],
121 | "strokeSharpness": "sharp",
122 | "seed": 1937240696,
123 | "version": 261,
124 | "versionNonce": 719308664,
125 | "isDeleted": false,
126 | "boundElements": null,
127 | "updated": 1646486544018,
128 | "link": null,
129 | "text": "state",
130 | "fontSize": 40.81628816725059,
131 | "fontFamily": 3,
132 | "textAlign": "left",
133 | "verticalAlign": "top",
134 | "baseline": 38.752788644215975,
135 | "containerId": null,
136 | "originalText": "state"
137 | },
138 | {
139 | "type": "text",
140 | "version": 210,
141 | "versionNonce": 1232899080,
142 | "isDeleted": false,
143 | "id": "sovW73tEcsyCufAslSP93",
144 | "fillStyle": "hachure",
145 | "strokeWidth": 1,
146 | "strokeStyle": "solid",
147 | "roughness": 1,
148 | "opacity": 100,
149 | "angle": 0,
150 | "x": 1108.617177872727,
151 | "y": 325.17474087682285,
152 | "strokeColor": "#364fc7",
153 | "backgroundColor": "transparent",
154 | "width": 24.943287213319802,
155 | "height": 48.752788644215975,
156 | "seed": 1158625400,
157 | "groupIds": [],
158 | "strokeSharpness": "sharp",
159 | "boundElements": [],
160 | "updated": 1646486544018,
161 | "link": null,
162 | "fontSize": 40.81628816725059,
163 | "fontFamily": 3,
164 | "text": ")",
165 | "baseline": 38.752788644215975,
166 | "textAlign": "left",
167 | "verticalAlign": "top",
168 | "containerId": null,
169 | "originalText": ")"
170 | },
171 | {
172 | "type": "text",
173 | "version": 248,
174 | "versionNonce": 57153656,
175 | "isDeleted": false,
176 | "id": "Bg55P55T1BKHSyexiQJmd",
177 | "fillStyle": "hachure",
178 | "strokeWidth": 1,
179 | "strokeStyle": "solid",
180 | "roughness": 1,
181 | "opacity": 100,
182 | "angle": 0,
183 | "x": 1031.3190434579828,
184 | "y": 325.2645282602143,
185 | "strokeColor": "#364fc7",
186 | "backgroundColor": "transparent",
187 | "width": 24.943287213319802,
188 | "height": 48.752788644215975,
189 | "seed": 656621320,
190 | "groupIds": [],
191 | "strokeSharpness": "sharp",
192 | "boundElements": [],
193 | "updated": 1646486544018,
194 | "link": null,
195 | "fontSize": 40.81628816725059,
196 | "fontFamily": 3,
197 | "text": "(",
198 | "baseline": 38.752788644215975,
199 | "textAlign": "left",
200 | "verticalAlign": "top",
201 | "containerId": null,
202 | "originalText": "("
203 | }
204 | ],
205 | "appState": {
206 | "gridSize": null,
207 | "viewBackgroundColor": "#ffffff"
208 | },
209 | "files": {}
210 | }
--------------------------------------------------------------------------------
/docs/interface/interface.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 1
3 | ---
4 |
5 | # Interface
6 |
7 | Antes de construirmos uma tela, com botões, inputs, imagens, precisamos definir como será o seu layout, por exemplo, se os itens serão posicionados na vertical ou horizontal. Na parte superior, teremos um slide com fotos fixo e abaixo uma lista de itens? São definições estruturais básicas e que devem ser feitas antes da customização (não se começa construindo uma casa, sem antes ter a planta em mãos).
8 |
9 | Com Flutter é a mesma coisa: Definimos o layout da nossa tela e então vamos adicionando widgets de interface.
10 |
11 | Imagine que você precisa construir o widget abaixo:
12 |
13 | 
14 |
15 | Podemos concluir que:
16 |
17 | * Os widgets devem ser exibidos horizontalmente;
18 | * O ícone e o texto devem ser exibidos verticalmente.
19 |
20 | Sendo um pouco mais _flutterista_:
21 |
22 | * Deve haver uma [Row](https://api.flutter.dev/flutter/widgets/Row-class.html) (linha) para que os widgets sejam exibidos na horizontal;
23 | * A Row será composta por 3 itens do tipo [Column](https://api.flutter.dev/flutter/widgets/Column-class.html) (coluna), para que os widgets sejam exibidos na vertical;
24 | * Os widgets dentro da [Column](https://api.flutter.dev/flutter/widgets/Column-class.html) devem ser: [Icon](https://api.flutter.dev/flutter/widgets/Icon-class.html) e [Text](https://api.flutter.dev/flutter/widgets/Text-class.html) .
25 |
26 | Então, temos:
27 |
28 | 
29 |
30 |
31 | :::tip
32 | Linhas e colunas farão parte de vários layouts que você irá construir, acostume-se.
33 | :::
34 |
35 | Vamos construir o layout:
36 |
37 | A coluna ([Column](https://api.flutter.dev/flutter/widgets/Column-class.html)) que contém o ícone ([Icon](https://api.flutter.dev/flutter/widgets/Icon-class.html)) e o texto ([Text](https://api.flutter.dev/flutter/dart-html/Text-class.html)).
38 |
39 | ```dart
40 | Column(
41 | children: [Icon(Icons.call), Text('Call')],
42 | )
43 | ```
44 |
45 | 
46 |
47 | Precisaremos de 3 widgets (a estrutura é a mesma, mudando apenas o ícone e o texto).
48 |
49 | Eles serão exibidos em linha horizontal ([Row](https://api.flutter.dev/flutter/widgets/Row-class.html)):
50 |
51 | ```dart
52 | Row(
53 | mainAxisAlignment: MainAxisAlignment.spaceEvenly,
54 | children: [
55 | Column(
56 | children: [Icon(Icons.call), Text('Call')],
57 | ),
58 | Column(
59 | children: [Icon(Icons.directions), Text('Route')],
60 | ),
61 | Column(
62 | children: [Icon(Icons.share), Text('Share')],
63 | ),
64 | ],
65 | )
66 | ```
67 |
68 | Pronto! Combinando widgets, montamos um outro widget que pode ser utilizado em qualquer lugar do nosso aplicativo.
69 |
70 |
75 |
76 | Algumas vezes, nossa tela será composta por uma lista (como a sua agenda de contatos, uma lista com vários itens). Para isso, utilizamos o widget [ListView](https://api.flutter.dev/flutter/widgets/ListView-class.html). Um widget comum para compor listas é o [ListTile](https://api.flutter.dev/flutter/material/ListTile-class.html).
77 |
78 | ```dart
79 | ListTile(
80 | title: Text('Flutter'),
81 | subtitle: Text('Tudo é um widget'),
82 | leading: Icon(Icons.flash_on),
83 | trailing: Icon(Icons.keyboard_arrow_right),
84 | ),
85 | ```
86 |
87 | 
88 |
89 | Agora, é só adicionar este widget à nossa lista, para criar cada item:
90 |
91 | ```dart
92 | ListView(
93 | children: [
94 | ListTile(
95 | title: Text('Flutter'),
96 | subtitle: Text('Tudo é um widget'),
97 | leading: Icon(Icons.flash_on),
98 | trailing: Icon(Icons.keyboard_arrow_right),
99 | ),
100 | ListTile(
101 | title: Text('Dart'),
102 | subtitle: Text('É fácil'),
103 | leading: Icon(Icons.mood),
104 | trailing: Icon(Icons.keyboard_arrow_right),
105 | ),
106 | ListTile(
107 | title: Text('Firebase'),
108 | subtitle: Text('Combina com Flutter'),
109 | leading: Icon(Icons.whatshot),
110 | trailing: Icon(Icons.keyboard_arrow_right),
111 | ),
112 | ],
113 | )
114 | ```
115 |
116 | 
117 |
118 |
123 |
124 | Outras vezes, precisaremos empilhar um widget sobre o outro:
125 |
126 | 
127 |
128 | Perceba que o texto está posicionado "acima" da imagem. O widget para termos esta pilha de widget é o [Stack](https://api.flutter.dev/flutter/widgets/Stack-class.htmlhttps://api.flutter.dev/flutter/widgets/Stack-class.html).
129 |
130 | ```dart
131 | Stack(
132 | children: [
133 | Container(
134 | width: 250,
135 | height: 250,
136 | color: Colors.blue,
137 | ),
138 | Container(
139 | width: 200,
140 | height: 200,
141 | color: Colors.red,
142 | ),
143 | Container(
144 | width: 150,
145 | height: 150,
146 | color: Colors.yellow,
147 | )
148 | ],
149 | )
150 | ```
151 |
152 | 
153 |
154 |
159 |
160 | Existem vários outros wigets que são utilizados para montar layouts. Para se aprofundar, recomendo que visite a seção [Layout](https://flutter.dev/docs/development/ui/widgets/layout) do catálogo de widgets.
161 |
--------------------------------------------------------------------------------
/static/img/conteudo-novo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/1-flutter.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 1
3 | slug: /flutter
4 | title: Flutter
5 | description: O que é o Flutter, por que utilizá-lo, origem e evolução
6 | keywords: [flutter, desenvolvimento de aplicativos, multiplataforma, google]
7 | ---
8 |
9 | ## O que é
10 |
11 | No site oficial, a definição do Flutter é a seguinte:
12 |
13 | **"Flutter transforma o processo de desenvolvimento de aplicativos. Construa, teste e implante belos aplicativos móveis, web, desktop e embarcados de alta qualidade a partir de um único código-fonte"**
14 |
15 | Em resumo: você escreve o código uma única vez e o seu aplicativo poderá ser executado em até seis plataformas diferentes.
16 |
17 | Utilizando a linguagem Dart \(que também foi criada pelo Google\), Flutter proporciona uma experiência incrível tanto para desenvolvedores quanto para usuários.
18 |
19 | Até a versão 1.2, Flutter era focado em entregar apps para iOS e Android. No entanto, com o lançamento da versão 1.5 foi lançada, durante o Google I/O 2019, o post oficial anunciava: **"Flutter não é mais um framework mobile, mas um framework multi-plataforma."**
20 |
21 |
22 |
23 |
24 |
25 | ---
26 |
27 | ## Vantagens
28 |
29 | Ele combina a beleza e a performance de aplicativos nativos com a flexibilidade e rapidez do desenvolvimento multiplataforma. Isso significa menos tempo de desenvolvimento, menos custos e mais rapidez na entrega do seu projeto. O Flutter é baseado em três pilares:
30 |
31 | * 🚀 Desenvolvimento rápido
32 | * 😍 Interfaces super bonitas
33 | * ⚡️ Performance nativa
34 |
35 | Devido a essas três características, ele já pode ser considerado um forte candidato para o desenvolvimento de aplicativos! Além disso, utilizando o Flutter, você tem vários benefícios:
36 |
37 | * **Multiplataforma:** O Flutter simplifica o processo de desenvolvimento de aplicativos para 6 plataformas diferentes, utilizando o mesmo código-fonte, reduzindo tempo e custo de desenvolvimento;
38 | * **Ecossistema**: Mais de 205 widgets \(componentes\) prontos para serem utilizados;
39 | * **Desempenho:** O código Dart é executado diretamente no dispositivo \(ao contrário de outros frameworks, o Flutter **não** utiliza componentes já existentes de cada plataform\);
40 | * **Personalização:** Todos os pixels na tela são "desenhados" pelo Flutter, o que torna o aplicativo altamente customizável e único;
41 | * **Performance:** Os plicativos rodam a 60 frames por segundo \(ou em até 120, se o dispositivo suportar\);
42 | * **Produtividade.** As alterações no código são refletidas no celular ou emulador em até 0,5s. Caso seja necessário reiniciar o app completamente, isso é feito em menos de 2 segundos;
43 | * **Google:** Criador e mantenedor da ferramenta, o Google utiliza o Flutter em seus principais aplicativos, como Ads e Pay. Além disso, também é o responsável pelos principais plugins para acesso à recursos nativos do celular \(bateria, câmera, conectividade, webview, etc \).
44 | * **Comunidade:** Além de ser ativa, o conteúdo produzido por ela garante uma curva de aprendizado mais suave e soluções para problemas comuns.
45 |
46 | Se você busca produtividade, o Flutter é a ferramenta ideal!
47 |
48 |
49 |
50 |
51 |
52 | ---
53 |
54 | ## Benefícios
55 |
56 | No universo da programação, sempre que surge uma nova linguagem/framework/tecnologia, é comum enaltecer os seus benefícios e os problemas à que se propõe resolver, mas pouco se fala sobre como as coisas são "do nosso lado". Desde o princípio, um dos grandes destaques do Flutter tem sido as funcionalidades que facilitam \(e muito!\) o nosso trabalho.
57 |
58 | Lembra que o primeiro dos três pilares é o desenvolvimento rápido? Pois bem, graças ao [hot reload](https://flutter.dev/docs/development/tools/hot-reload) e ao hot restart, temos uma experiência incrível ao desenvolver um app.
59 |
60 |
61 | ### Hot reload
62 |
63 | As alterações realizadas no código são refletidas em até 0,5s \(no emulador ou aparelho\) e sem perder o estado da aplicação, o que é muito importante. Imagine um fluxo de carrinho de compras em que precisamos alterar a mensagem de "compra realizada com sucesso":
64 |
65 | :::tip
66 |
67 | adicionar os produtos -> proceder para o checkout -> realizar o pagamento -> "compra realizada com sucesso"
68 |
69 | :::
70 |
71 | Percorrer todo esse fluxo à cada alteração para verificar o resultado final irá consumir bastante tempo. Mas não com Flutter, utilizando o hot reload.
72 |
73 | As alterações realizadas no código são refletidas em até 0,5s (no emulador ou aparelho), sem perder o estado da aplicação, o que é muito importante. Imagine um fluxo de carrinho de compras em que precisamos alterar a mensagem "compra realizada com sucesso", após adicionar os produtos, proceder ao checkout e realizar o pagamento. Percorrer todo esse fluxo a cada alteração para verificar o resultado final consumiria bastante tempo. Mas não com o Flutter, utilizando o hot reload.
74 |
75 | ### Hot restart
76 |
77 | Quando o aplicativo é reinicializado, ou seja, perde-se o estado atual, todo o processo ocorre em menos de 2s. Alguns tipos de alterações exigem que seja feito um hot restart.
78 |
79 | ### Mágica
80 |
81 | Quando alteramos o código, a Dart VM \(virtual machine\) consegue identificar esta alteração e sobrepõe a classe antiga com esta nova, portanto, apenas aquela parte alterada será reconstruída.
82 |
83 |
84 |
85 |
86 |
87 | ---
88 |
89 | ## Origem
90 |
91 | O projeto foi iniciado em 2014, com o codinome "sky", com o intuito de encontrar uma melhor maneira de construir interfaces para o mobile. Em 2015, foi [apresentado](https://www.youtube.com/watch?v=PnIWl33YMwA&t=67s) durante a Dart Developer Summit, onde foi possível ver o código Dart sendo executado em um aparelho Android e também apresentado com o nome **Flutter**. Em 2016, no mesmo evento, Flutter foi [definido](https://www.youtube.com/watch?v=Mx-AllVZ1VY&t=76s) como _"Uma melhor maneira de desenvolvimento mobile"_. A estréia do Flutter em um grande evento foi no Google IO 2017, em uma [sessão](https://www.youtube.com/watch?v=w2TcYP8qiRI&t=1773s) de "live coding", onde o app construido foi integrado ao Firebase e com acesso à camera. No Google IO 2018, com uma grande expectativa, Flutter já teve um destaque maior, contando com 3 excelentes palestras, cobrindo tópicos como [gerenciamento de estado](https://www.youtube.com/watch?v=RS36gBEp8OI), uso do [Material Design](https://www.youtube.com/watch?v=hA0hrpR-o8U) e novamente outra [sessão](https://www.youtube.com/watch?v=p4yLzYwy_4g) "live coding" de um app acessando o Firebase.
92 |
93 | Em dezembro de 2018, finalmente foi [lançada](https://www.youtube.com/watch?v=D-o4BqJxmJE) a versão 1.0 e dentre tantas novidades, o principal destaque foi para o projeto Hummingbird, que futuramente se tornou o Flutter para Web.
94 |
95 |
96 | :::note Curiosidade
97 | Toda a apresentação da versão 1.0 foi feita em um aplicativo nativo para macOS, utilizando o Flutter.
98 | :::
99 |
100 | ---
101 |
102 | ## Evolução
103 |
104 | 2017: Single Codebase, Two Apps
105 |
106 | 2018: Production ready
107 |
108 | 2019: A portable UI Framework
109 |
110 | 2020: *no event*
111 | 2021: Leading UI toolkit for multiplatform
112 |
113 | 2022: From a mobile-centric to a multiplatform
114 |
115 | 2023: Game-changer in the industry
--------------------------------------------------------------------------------
/static/img/arquitetura.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/gerenciamento-estado/bloc.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 5
3 | ---
4 |
5 | # BLoC
6 |
7 | **B**usiness **L**ogic **o**f **C**omponent \(ou BLoC para os íntimos\) é um padrão apresentado pelo Google na [DartConf 2018](https://www.youtube.com/watch?v=PLHln7wHgPE), sobre o compartilhamento de código entre o Flutter e o [AngularDart](https://angulardart.dev).
8 |
9 | Usando Flutter para a versão mobile e AngularDart para a versão web, como podemos gerenciar o estado do aplicativo, com menos esforço possível? Utilizando uma solução que esteja disponível para as duas plataformas, que neste caso são [Streams](https://dart.dev/tutorials/language/streams)
10 |
11 | :::tip
12 | Stream é uma sequência de **eventos** assíncronos.
13 | :::
14 |
15 | As opções apresentadas anteriormente utilizam recursos internos do Flutter e que não podemos utilizar fora do framework.
16 |
17 | Streams são um recurso nativo da linguagem Dart, ou seja, podemos utilizá-las independente da plataforma. Sendo assim, nossa solução de gerenciamento de estado é puramente código Dart, podendo ser utilizada com Flutter e AngularDart.
18 |
19 | Por ser um componente lógico, o BLoC não se preocupa com a interface e nem com a sua camada de dados ou API. Ele entende "apenas" de eventos. Os widgets emitem eventos e outros widgets podem respondem à estes eventos. Com este padrão é possível separar a lógica de negócio e a interface.
20 |
21 | Com a imagem abaixo, ficará mais fácil de entender:
22 |
23 | 
24 |
25 | O coração de um BLoC é a [StreamController](https://api.dart.dev/stable/2.4.1/dart-async/StreamController-class.html).
26 |
27 | Com ela, temos acesso às propriedades [sink](https://api.dart.dev/stable/2.4.1/dart-async/StreamController/sink.html) \(entrada\) e a [stream](https://api.dart.dev/stable/2.4.1/dart-async/StreamController/stream.html) \(saída\).
28 |
29 | Com estes três componentes temos tudo o que é necessário para implementar o padrão BLoC.
30 |
31 | :::info
32 | Eventos são quaisquer ações que alteram o estado da nossa aplicação. Seja a chamda para uma API, o usuário fazendo login e até mesmo o incremento de um contador.
33 | :::
34 |
35 | 1. Eventos são emitidos para o nosso BLoC, via sink;
36 | 2. O BLoC recebe o evento e aplica alguma lógica de negócio;
37 | 3. A saída do evento é colocada na stream;
38 | 4. Todos que estejam "ouvindo" a stream do nosso BLoC são notificados de que há um novo valor para ela.
39 |
40 | :::warning
41 | Mesmo citando widgets \(que são componentes do Flutter\), os eventos poderiam ser disparados por componentes do AngularDart. Lembre-se que o BLoC foi apresentado para facilitar o compartilhamento de código entre a web e mobile.
42 | :::
43 |
44 | ## BLoC no Flutter
45 |
46 | Agora já sabemos sobre o padrão e iremos descobrir como implementá-los no nosso aplicativo. Para isso, o framework nos fornece o widget [StreamBuilder](https://api.flutter.dev/flutter/widgets/StreamBuilder-class.html).
47 |
48 | Falaremos mais tarde, antes, precisamos implementar nosso BLoC.
49 |
50 | ```dart
51 | class MeuBloc {
52 | int _total = 0;
53 | int get total => _total;
54 |
55 | final _blocController = StreamController();
56 |
57 | Stream get minhaStream => _blocController.stream;
58 |
59 | void incrementar() {
60 | _total++;
61 | _blocController.sink.add(total);
62 | }
63 |
64 | fecharStream() {
65 | _blocController.close();
66 | }
67 | }
68 | ```
69 |
70 | 1. Temos uma **`total`** propriedade do tipo int \(privada\);
71 | 2. Criamos um método **get** para acessá-la;
72 | 3. Declaramos nossa **StreamController;**
73 | 4. Criamos um método **get** para acessar a stream da nossa StreamController;
74 | 5. Criamos o méotodo **`incrementar()`** para incrementar o valor de `total` e com o método `add()` da propriedade `sink`, adicionamos o valor já incrementado à nossa StreamController;
75 | 6. Criamos o méotodo **`fecharStream()`** para fechar nosso `_blocController`.
76 |
77 | :::note
78 | O não fechamento **StreamController** implica na utilização de memória de forma desnecessária, isso pode ocasionar perda de desempenho e falhas na aplicação.
79 | :::
80 |
81 | :::tip
82 | Já temos nosso componente lógico pronto.
83 | :::
84 |
85 | Portanto, já podemos utilizá-lo para construir nossa interface. Chegou a hora de conhecer melhor o widget que irá ouvir a **stream** da nossa StreamController e "reagir" à qualquer novo evento emitido pela stream.
86 |
87 | ### StreamBuilder
88 |
89 | Este widget fica "ouvindo" uma stream e sempre que há um novo evento, ele é reconstruído \(o método **builder** é executado novamente\).
90 |
91 | ```dart
92 | StreamBuilder(
93 | stream: minhaStream, //stream do tipo int
94 | builder: (BuildContext context, AsyncSnapshot snapshot) {
95 | if (snapshot.hasError) {
96 | return Text('Erro com a stream');
97 | } else {
98 | return Text('$snapshot.data');
99 | }
100 | },
101 | )
102 | ```
103 |
104 | Vamos analisar:
105 |
106 | 1. Declaramos nosso widget **StreamBuilder** \(com o tipo int\);
107 | 2. Na propriedade stream, indicamos qual **stream** queremos "ouvir";
108 | 3. Implementamos a função **builder**. Ela recebe como parâmetro o [BuildContext](https://api.flutter.dev/flutter/widgets/BuildContext-class.html) e um [AsyncSnapshot](https://api.flutter.dev/flutter/widgets/AsyncSnapshot-class.html) \(não se preocupe com isso agora\).
109 | 4. Caso nossa stream contenha algum erro, retornamos um texto informativo;
110 | 5. Se não houver nenhum problemas, exibimos o dado do snapshot \(.data\) que é o último valor recebido pela stream;
111 | 6. Para que nosso `_blocController` seja encerrado de maneira correta, precisamos sobrescrever o método `dispose` \(\_HomePageState\);
112 |
113 | Um exemplo completo do aplicativo Contador utilizando o padrão BLoC:
114 |
115 | ```dart
116 | import 'package:flutter/material.dart';
117 | import 'dart:async';
118 |
119 | void main() => runApp(BlocApp());
120 |
121 | class BlocApp extends StatelessWidget {
122 | @override
123 | Widget build(BuildContext context) {
124 | return MaterialApp(
125 | title: 'Flutter para Iniciantes - BLoC',
126 | debugShowCheckedModeBanner: false,
127 | home: HomePage(),
128 | );
129 | }
130 | }
131 |
132 | class HomePage extends StatefulWidget {
133 | @override
134 | _HomePageState createState() => _HomePageState();
135 | }
136 |
137 | class _HomePageState extends State {
138 | MeuBloc bloc = MeuBloc();
139 |
140 | @override
141 | Widget build(BuildContext context) {
142 | return Scaffold(
143 | appBar: AppBar(
144 | title: Text('Flutter para Iniciantes - BLoC'),
145 | ),
146 | body: Center(
147 | child: Column(
148 | mainAxisAlignment: MainAxisAlignment.center,
149 | children: [
150 | StreamBuilder(
151 | stream: bloc.minhaStream,
152 | initialData: 0,
153 | builder: (context, snapshot) {
154 | if (snapshot.hasError) {
155 | return Text('Há um erro na Stream');
156 | } else {
157 | return Text(
158 | '${snapshot.data}',
159 | style: Theme.of(context).textTheme.headline4,
160 | );
161 | }
162 | }),
163 | ],
164 | ),
165 | ),
166 | floatingActionButton: FloatingActionButton(
167 | onPressed: bloc.incrementar,
168 | tooltip: 'Increment',
169 | child: Icon(Icons.add),
170 | ),
171 | );
172 | }
173 | @override
174 | void dispose() {
175 | bloc.fecharStream();
176 | super.dispose();
177 | }
178 | }
179 |
180 | class MeuBloc {
181 | int _total = 0;
182 |
183 | int get total => _total;
184 |
185 | // 1
186 | final _blocController = StreamController();
187 |
188 | // 2
189 | Stream get minhaStream => _blocController.stream;
190 |
191 | // 3
192 | void incrementar() {
193 | _total++;
194 | _blocController.sink.add(total);
195 | }
196 |
197 | fecharStream() {
198 | _blocController.close();
199 | }
200 | }
201 | ```
202 |
203 | Brinque com ele também no [DartPad](https://dartpad.dev/b6409e10de32b280b8938aa75364fa7b).
204 |
--------------------------------------------------------------------------------
/static/img/embedder.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/static/img/arquitetura.excalidraw:
--------------------------------------------------------------------------------
1 | {
2 | "type": "excalidraw",
3 | "version": 2,
4 | "source": "https://excalidraw.com",
5 | "elements": [
6 | {
7 | "type": "rectangle",
8 | "version": 213,
9 | "versionNonce": 1279652951,
10 | "isDeleted": false,
11 | "id": "qxM3bjO-LwYDLfELDsJIf",
12 | "fillStyle": "solid",
13 | "strokeWidth": 4,
14 | "strokeStyle": "solid",
15 | "roughness": 1,
16 | "opacity": 100,
17 | "angle": 0,
18 | "x": 637.9857378576966,
19 | "y": 279.4992188821612,
20 | "strokeColor": "#000000",
21 | "backgroundColor": "#ced4da",
22 | "width": 648.6062174572046,
23 | "height": 56.756437463746686,
24 | "seed": 105393975,
25 | "groupIds": [],
26 | "frameId": null,
27 | "roundness": {
28 | "type": 1
29 | },
30 | "boundElements": [],
31 | "updated": 1692468447789,
32 | "link": null,
33 | "locked": false
34 | },
35 | {
36 | "type": "text",
37 | "version": 271,
38 | "versionNonce": 944345303,
39 | "isDeleted": false,
40 | "id": "FJEQv-DaiVbXf8tZ9ls4g",
41 | "fillStyle": "solid",
42 | "strokeWidth": 4,
43 | "strokeStyle": "solid",
44 | "roughness": 1,
45 | "opacity": 100,
46 | "angle": 0,
47 | "x": 892.1178015404826,
48 | "y": 289.84628984487705,
49 | "strokeColor": "#000000",
50 | "backgroundColor": "transparent",
51 | "width": 106.91583815141391,
52 | "height": 35.99113603363471,
53 | "seed": 1747847673,
54 | "groupIds": [],
55 | "frameId": null,
56 | "roundness": {
57 | "type": 2
58 | },
59 | "boundElements": [],
60 | "updated": 1692468451132,
61 | "link": null,
62 | "locked": false,
63 | "fontSize": 29.992613361362274,
64 | "fontFamily": 3,
65 | "text": "CÓDIGO",
66 | "textAlign": "left",
67 | "verticalAlign": "top",
68 | "containerId": null,
69 | "originalText": "CÓDIGO",
70 | "lineHeight": 1.1999999999999995,
71 | "baseline": 28.991136033634724
72 | },
73 | {
74 | "type": "rectangle",
75 | "version": 263,
76 | "versionNonce": 2043478841,
77 | "isDeleted": false,
78 | "id": "HElTSmRuBSsRKnua-vuF9",
79 | "fillStyle": "solid",
80 | "strokeWidth": 4,
81 | "strokeStyle": "solid",
82 | "roughness": 1,
83 | "opacity": 100,
84 | "angle": 0,
85 | "x": 638.3288442588973,
86 | "y": 346.7819671472888,
87 | "strokeColor": "#000000",
88 | "backgroundColor": "#a5d8ff",
89 | "width": 648.6062174572046,
90 | "height": 58.3675312166837,
91 | "seed": 274497687,
92 | "groupIds": [],
93 | "frameId": null,
94 | "roundness": {
95 | "type": 1
96 | },
97 | "boundElements": [],
98 | "updated": 1692468354789,
99 | "link": null,
100 | "locked": false
101 | },
102 | {
103 | "type": "text",
104 | "version": 484,
105 | "versionNonce": 583458713,
106 | "isDeleted": false,
107 | "id": "dfw1-xWnO1rtBNNjg8wcL",
108 | "fillStyle": "solid",
109 | "strokeWidth": 4,
110 | "strokeStyle": "solid",
111 | "roughness": 1,
112 | "opacity": 100,
113 | "angle": 0,
114 | "x": 891.8556608516816,
115 | "y": 357.6943320170793,
116 | "strokeColor": "#000000",
117 | "backgroundColor": "transparent",
118 | "width": 160.37375722712088,
119 | "height": 35.99113603363473,
120 | "seed": 1395571127,
121 | "groupIds": [],
122 | "frameId": null,
123 | "roundness": {
124 | "type": 2
125 | },
126 | "boundElements": [],
127 | "updated": 1692468360263,
128 | "link": null,
129 | "locked": false,
130 | "fontSize": 29.992613361362277,
131 | "fontFamily": 3,
132 | "text": "FRAMEWORK",
133 | "textAlign": "left",
134 | "verticalAlign": "top",
135 | "containerId": null,
136 | "originalText": "FRAMEWORK",
137 | "lineHeight": 1.2000000000000002,
138 | "baseline": 28.991136033634724
139 | },
140 | {
141 | "type": "rectangle",
142 | "version": 304,
143 | "versionNonce": 852833335,
144 | "isDeleted": false,
145 | "id": "l5R5Aj1QYA-xZ7o1L2KFD",
146 | "fillStyle": "solid",
147 | "strokeWidth": 4,
148 | "strokeStyle": "solid",
149 | "roughness": 1,
150 | "opacity": 100,
151 | "angle": 0,
152 | "x": 636.7973065553383,
153 | "y": 416.05631886771863,
154 | "strokeColor": "#000000",
155 | "backgroundColor": "#b2f2bb",
156 | "width": 648.6062174572046,
157 | "height": 57.561984340215204,
158 | "seed": 1221685337,
159 | "groupIds": [],
160 | "frameId": null,
161 | "roundness": {
162 | "type": 1
163 | },
164 | "boundElements": [],
165 | "updated": 1692468389481,
166 | "link": null,
167 | "locked": false
168 | },
169 | {
170 | "type": "text",
171 | "version": 611,
172 | "versionNonce": 2003865273,
173 | "isDeleted": false,
174 | "id": "VzJ31mx2AHRWfWUE19Hcy",
175 | "fillStyle": "solid",
176 | "strokeWidth": 4,
177 | "strokeStyle": "solid",
178 | "roughness": 1,
179 | "opacity": 100,
180 | "angle": 0,
181 | "x": 890.671951481798,
182 | "y": 426.3317529685912,
183 | "strokeColor": "#000000",
184 | "backgroundColor": "transparent",
185 | "width": 106.91583815141391,
186 | "height": 35.99113603363473,
187 | "seed": 2071928247,
188 | "groupIds": [],
189 | "frameId": null,
190 | "roundness": {
191 | "type": 2
192 | },
193 | "boundElements": [],
194 | "updated": 1692468389481,
195 | "link": null,
196 | "locked": false,
197 | "fontSize": 29.992613361362274,
198 | "fontFamily": 3,
199 | "text": "ENGINE",
200 | "textAlign": "left",
201 | "verticalAlign": "top",
202 | "containerId": null,
203 | "originalText": "ENGINE",
204 | "lineHeight": 1.2000000000000002,
205 | "baseline": 28.991136033634724
206 | },
207 | {
208 | "type": "rectangle",
209 | "version": 362,
210 | "versionNonce": 885340759,
211 | "isDeleted": false,
212 | "id": "FCDOJxOcECV3GbyxDWtBh",
213 | "fillStyle": "solid",
214 | "strokeWidth": 4,
215 | "strokeStyle": "solid",
216 | "roughness": 1,
217 | "opacity": 100,
218 | "angle": 0,
219 | "x": 636.7973065553383,
220 | "y": 484.4021425399642,
221 | "strokeColor": "#000000",
222 | "backgroundColor": "#ffec99",
223 | "width": 648.6062174572046,
224 | "height": 55.95089058727827,
225 | "seed": 1828388407,
226 | "groupIds": [],
227 | "frameId": null,
228 | "roundness": {
229 | "type": 1
230 | },
231 | "boundElements": [],
232 | "updated": 1692468411763,
233 | "link": null,
234 | "locked": false
235 | },
236 | {
237 | "type": "text",
238 | "version": 564,
239 | "versionNonce": 1359182489,
240 | "isDeleted": false,
241 | "id": "KXOB1pxEmZK434XQAgvX6",
242 | "fillStyle": "solid",
243 | "strokeWidth": 4,
244 | "strokeStyle": "solid",
245 | "roughness": 1,
246 | "opacity": 100,
247 | "angle": 0,
248 | "x": 890.7616159361519,
249 | "y": 494.163479408561,
250 | "strokeColor": "#000000",
251 | "backgroundColor": "transparent",
252 | "width": 106.44187039734526,
253 | "height": 35.99113603363473,
254 | "seed": 853828793,
255 | "groupIds": [],
256 | "frameId": null,
257 | "roundness": {
258 | "type": 2
259 | },
260 | "boundElements": [],
261 | "updated": 1692468411763,
262 | "link": null,
263 | "locked": false,
264 | "fontSize": 29.992613361362274,
265 | "fontFamily": 3,
266 | "text": "RUNNER",
267 | "textAlign": "left",
268 | "verticalAlign": "top",
269 | "containerId": null,
270 | "originalText": "RUNNER",
271 | "lineHeight": 1.2000000000000002,
272 | "baseline": 28.991136033634724
273 | },
274 | {
275 | "type": "rectangle",
276 | "version": 429,
277 | "versionNonce": 895362105,
278 | "isDeleted": false,
279 | "id": "MeifjWlklBsaPyN6c0E1r",
280 | "fillStyle": "solid",
281 | "strokeWidth": 4,
282 | "strokeStyle": "solid",
283 | "roughness": 1,
284 | "opacity": 100,
285 | "angle": 0,
286 | "x": 634.5,
287 | "y": 549.8709473839256,
288 | "strokeColor": "#000000",
289 | "backgroundColor": "#ffc9c9",
290 | "width": 648.6062174572046,
291 | "height": 51.92315620493601,
292 | "seed": 1365224537,
293 | "groupIds": [],
294 | "frameId": null,
295 | "roundness": {
296 | "type": 1
297 | },
298 | "boundElements": [],
299 | "updated": 1692468440454,
300 | "link": null,
301 | "locked": false
302 | },
303 | {
304 | "type": "text",
305 | "version": 626,
306 | "versionNonce": 1915754455,
307 | "isDeleted": false,
308 | "id": "gO6gxGHm4EzX5xovoRMwB",
309 | "fillStyle": "solid",
310 | "strokeWidth": 4,
311 | "strokeStyle": "solid",
312 | "roughness": 1,
313 | "opacity": 100,
314 | "angle": 0,
315 | "x": 891.0006583106292,
316 | "y": 558.6322842525224,
317 | "strokeColor": "#000000",
318 | "backgroundColor": "transparent",
319 | "width": 141.66723757920053,
320 | "height": 35.99113603363473,
321 | "seed": 922919351,
322 | "groupIds": [],
323 | "frameId": null,
324 | "roundness": {
325 | "type": 2
326 | },
327 | "boundElements": [],
328 | "updated": 1692468440454,
329 | "link": null,
330 | "locked": false,
331 | "fontSize": 29.992613361362274,
332 | "fontFamily": 3,
333 | "text": "HARDWARE",
334 | "textAlign": "left",
335 | "verticalAlign": "top",
336 | "containerId": null,
337 | "originalText": "HARDWARE",
338 | "lineHeight": 1.2000000000000002,
339 | "baseline": 28.991136033634724
340 | }
341 | ],
342 | "appState": {
343 | "gridSize": null,
344 | "viewBackgroundColor": "#ffffff"
345 | },
346 | "files": {}
347 | }
--------------------------------------------------------------------------------
/static/img/navegacao-light.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/static/img/navegacao-dark.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------