Criar seu primeiro app do Flutter, parte 2

O Flutter é um kit de ferramentas de IU do Google para criar apps incríveis e nativos para dispositivos móveis, Web e computadores com uma única base de código. Ele funciona com código existente, é usado por desenvolvedores e organizações do mundo todo, é gratuito e de código aberto.

Neste codelab, você ampliará um app básico do Flutter para dispositivos móveis para incluir interatividade. Você também criará uma segunda página, chamada rota, que o usuário poderá acessar. Por fim, você modificará o tema (cor) do app. O codelab amplia a parte 1, em que você cria uma lista infinita de carregamento lento. Mas, se você quiser começar pela parte 2, forneceremos o código inicial.

O que você aprenderá na parte 2

  • Como criar um app do Flutter que pareça natural no iOS, no Android e na Web.
  • Como usar a recarga dinâmica para ter um ciclo de desenvolvimento mais rápido.
  • Como adicionar interatividade a um widget com estado.
  • Como criar e navegar para uma segunda tela.
  • Como mudar a aparência de um app usando temas.

O que você criará na parte 2

Você começará com um app simples para dispositivos móveis que gera uma lista infinita de sugestões de nomes para uma empresa startup. Ao final do codelab, os usuários finais poderão selecionar e desmarcar nomes, salvando os melhores. Tocar no ícone de lista, no canto superior direito da barra de apps, direciona para uma nova página, chamada de rota, que lista apenas os nomes adicionados aos favoritos.

O GIF animado a seguir mostra como o app final funcionará.

7fcab088cd22cff7.gif

O que você quer aprender com este codelab?

Ainda não conheço bem o assunto e quero ter uma boa visão geral. Conheço um pouco sobre esse assunto, mas quero me atualizar. Estou procurando exemplos de código para usar no meu projeto. Estou procurando uma explicação de algo específico.

Se você não concluiu a Parte 1 deste codelab, consulte Configurar seu ambiente do Flutter em Criar seu primeiro app do Flutter, parte 1, para configurar seu ambiente para desenvolvimento do Flutter.

Se você já concluiu a parte 1, já tem o app inicial startup_namer. Continue para a próxima etapa.

Se você não tem o startup_namer, não se preocupe, basta seguir as instruções abaixo.

b2f84ff91b0e1396.pngPrograme um app do Flutter simples usando um modelo. Crie um projeto do Flutter chamado startup_namer e migre-o para um sistema de segurança contra nulidade como mostrado a seguir.

$ flutter create startup_namer
$ cd startup_namer
$ dart migrate --apply-changes

Você editará principalmente o lib/main.dart, onde fica o código Dart.

b2f84ff91b0e1396.png Exclua todo o código do lib/main.dart. Substitua-o pelo código deste arquivo, que exibe uma lista infinita de carregamento lento com sugestões de nomes para startups.

b2f84ff91b0e1396.png Atualize o pubspec.yaml adicionando o pacote de palavras em inglês:

dependencies:
  flutter:
    sdk: flutter

  cupertino_icons: ^1.0.2
  english_words: ^4.0.0-0    // NEW

O pacote de palavras em inglês gera pares de palavras aleatórias, que são usadas como possíveis nomes para startups.

b2f84ff91b0e1396.png Ao ver o pubspec na visualização de edição do Android Studio, clique em Pub get no canto superior direito, que extrai o pacote para seu projeto. Você verá o seguinte no console:

flutter pub get
Running "flutter pub get" in startup_namer...
Process finished with exit code 0

b2f84ff91b0e1396.png Execute o app.

Role a tela o quanto quiser e você verá uma oferta contínua de sugestões de nomes para startups.

Nesta etapa, você adicionará ícones de coração a cada linha. Na etapa seguinte, você os tornará tocáveis e salvará os favoritos.

b2f84ff91b0e1396.png Adicione uma _saved Set à classe _RandomWordsState. Essa Set armazena os pares de palavras que o usuário adiciona como favoritos. A Set é preferida em relação à List, porque uma Set implementada corretamente não autoriza entradas duplicadas.

class _RandomWordsState extends State<RandomWords> {
  final _suggestions = <WordPair>[];
  final _saved = <WordPair>{};     // NEW
  final _biggerFont = TextStyle(fontSize: 18.0);
  ...
}

b2f84ff91b0e1396.png Na função _buildRow, adicione uma verificação alreadySaved para garantir que um par de palavras ainda não foi adicionado aos favoritos.

Widget _buildRow(WordPair pair) {
  final alreadySaved = _saved.contains(pair);  // NEW
  ...
}

Na _buildRow(), você também adicionará ícones em forma de coração aos objetos ListTile para ativar os favoritos. Na próxima etapa, você acrescentará a possibilidade de interagir com os ícones de coração.

b2f84ff91b0e1396.png Adicione os ícones após o texto, conforme mostrado abaixo:

Widget _buildRow(WordPair pair) {
  final alreadySaved = _saved.contains(pair);
  return ListTile(
    title: Text(
      pair.asPascalCase,
      style: _biggerFont,
    ),
    trailing: Icon(   // NEW from here...
      alreadySaved ? Icons.favorite : Icons.favorite_border,
      color: alreadySaved ? Colors.red : null,
    ),                // ... to here.
  );
}

b2f84ff91b0e1396.png Faça uma recarga dinâmica do app.

Agora, você verá corações em cada linha, mas eles ainda não são interativos.

Android

iOS

Problemas?

Caso seu app não esteja sendo executado corretamente, use o código do link a seguir para colocar tudo de volta nos eixos.

Nesta etapa, você fará os ícones de coração serem tocáveis. Quando o usuário toca em uma entrada na lista, alternando o estado de favorito dela, esse par de palavras é adicionado ou removido de um conjunto de favoritos salvos.

Para fazer isso, você modificará a função _buildRow. Se uma entrada de palavra já tiver sido adicionada aos favoritos, toque nela novamente para removê-la. Quando um bloco é tocado, a função chama setState() para notificar o framework sobre a mudança do estado.

b2f84ff91b0e1396.png Adicione onTap ao método _buildRow, como mostrado abaixo:

Widget _buildRow(WordPair pair) {
  final alreadySaved = _saved.contains(pair);
  return ListTile(
    title: Text(
      pair.asPascalCase,
      style: _biggerFont,
    ),
    trailing: Icon(
      alreadySaved ? Icons.favorite : Icons.favorite_border,
      color: alreadySaved ? Colors.red : null,
    ),
    onTap: () {      // NEW lines from here...
      setState(() {
        if (alreadySaved) {
          _saved.remove(pair);
        } else {
          _saved.add(pair);
        }
      });
    },               // ... to here.
  );
}

b2f84ff91b0e1396.png Faça uma recarga dinâmica do app.

Você pode tocar em qualquer bloco para adicionar a entrada aos favoritos ou removê-la. Tocar em um bloco gera uma animação de respingo de tinta implícita, saindo do ponto do toque.

Android

iOS

Problemas?

Caso seu app não esteja sendo executado corretamente, use o código do link a seguir para colocar tudo de volta nos eixos.

Nesta etapa, você adicionará uma nova página no Flutter, chamada rota, que exibe os favoritos. Você aprenderá a navegar entre a rota inicial e a nova.

No Flutter, o Navigator gerencia uma pilha que contém as rotas do app. Enviar uma rota para a pilha do Navigator atualiza a exibição para essa rota. Ao mover uma rota da pilha do Navigator, a exibição volta para a rota anterior.

Em seguida, você adicionará um ícone de lista à AppBar no método build da _RandomWordsState. Quando o usuário clicar no ícone de lista, uma nova rota com os favoritos salvos será enviada para o Navigator, exibindo o ícone.

b2f84ff91b0e1396.png Adicione o ícone e a ação correspondente ao método build:

class _RandomWordsState extends State<RandomWords> {
  ...
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Startup Name Generator'),
        actions: [
          IconButton(icon: Icon(Icons.list), onPressed: _pushSaved),
        ],
      ),
      body: _buildSuggestions(),
    );
  }
  ...
}

b2f84ff91b0e1396.png Adicione uma função _pushSaved() à classe _RandomWordsState.

  void _pushSaved() {
  }

b2f84ff91b0e1396.png Faça uma recarga dinâmica do app. O ícone de lista a114478ae13b853.png aparecerá na barra de apps. Se você tocar nele, nada acontecerá ainda, porque a função _pushSaved está vazia.

Em seguida, você criará uma rota e a enviará para a pilha do Navigator. Essa ação muda a tela para exibir a nova rota. O conteúdo da nova página é criado na propriedade builder da MaterialPageRoute em uma função anônima.

b2f84ff91b0e1396.png Chame o Navigator.push, conforme mostrado abaixo, que envia a rota para a pilha do Navigator. O ambiente de desenvolvimento integrado reclamará do código inválido, mas você poderá corrigi-lo na próxima seção.

void _pushSaved() {
  Navigator.of(context).push(
  );
}

Em seguida, você adicionará a MaterialPageRoute e o builder dela. Por enquanto, adicione o código que gera as linhas ListTile. O método divideTiles() da ListTile adiciona espaçamento horizontal entre cada ListTile. A variável divided mantém as linhas finais convertidas em uma lista pela função de conveniência, toList().

b2f84ff91b0e1396.png Adicione o código, conforme mostrado no snippet de código a seguir:

  void _pushSaved() {
    Navigator.of(context).push(
      MaterialPageRoute<void>(
        // NEW lines from here...
        builder: (BuildContext context) {
          final tiles = _saved.map(
            (WordPair pair) {
              return ListTile(
                title: Text(
                  pair.asPascalCase,
                  style: _biggerFont,
                ),
              );
            },
          );
          final divided = ListTile.divideTiles(
            context: context,
            tiles: tiles,
          ).toList();

          return Scaffold(
            appBar: AppBar(
              title: Text('Saved Suggestions'),
            ),
            body: ListView(children: divided),
          );
        }, // ...to here.
      ),
    );
  }

A propriedade builder retorna um Scaffold que contém a barra de apps para a nova rota, chamada SavedSuggestions. O corpo da nova rota consiste em uma ListView com as linhas ListTiles. Cada linha é separada por um divisor.

b2f84ff91b0e1396.png Faça uma recarga dinâmica do app. Marque algumas das seleções como favoritas e toque no ícone de lista na barra de apps. A nova rota aparecerá com os favoritos. Observe que o Navigator adiciona um botão "Voltar" à barra de apps. Você não precisava implementar o Navigator.pop explicitamente. Toque no botão "Voltar" para retornar à rota inicial.

iOS - Rota principal

iOS - Rota de sugestões salvas

Problemas?

Caso seu app não esteja sendo executado corretamente, use o código do link a seguir para colocar tudo de volta nos eixos.

Nesta etapa, você modificará o tema do app. O tema controla a aparência do app. Você pode usar o tema padrão, que depende do dispositivo físico ou emulador, ou personalizá-lo para refletir sua marca.

Você pode mudar o tema de um app facilmente configurando a classe ThemeData. O app usa o tema padrão, mas você mudará a cor principal dele para branco.

b2f84ff91b0e1396.png Mude a cor na classe MyApp:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Startup Name Generator',
      theme: ThemeData(          // Add the 3 lines from here...
        primaryColor: Colors.white,
      ),                         // ... to here.
      home: RandomWords(),
    );
  }
}

b2f84ff91b0e1396.png Faça uma recarga dinâmica do app. O plano de fundo agora está branco, até mesmo a barra de apps.

Como um exercício, use ThemeData para mudar outros aspectos da IU. A classe Colors da biblioteca do Material Design oferece várias constantes de cor que você pode testar. A recarga dinâmica torna os experimentos com a IU mais fáceis e rápidos.

Android

iOS

Problemas?

Caso você tenha se perdido, use o código do link a seguir para ver o código do app final.

Você escreveu um app interativo do Flutter que pode ser executado no iOS e Android ao fazer o seguinte:

  • Escrever código Dart.
  • Usar a recarga dinâmica para um ciclo de desenvolvimento mais rápido.
  • Implementar um widget com estado, adicionando interatividade ao app.
  • Criar uma rota e adicionar lógica para mover entre a rota inicial e a nova.
  • Aprender a mudar a aparência da IU do app usando temas.

Saiba mais sobre o SDK do Flutter com os seguintes recursos (links em inglês):

Veja outros recursos (links em inglês):

Além disso, conecte-se à comunidade do Flutter (em inglês).