Alura > Cursos de Mobile > Cursos de Flutter > Conteúdos de Flutter > Primeiras aulas do curso Flutter: aplicando constraints e implementando layouts responsivos

Flutter: aplicando constraints e implementando layouts responsivos

Iniciando o projeto - Apresentação

Olá! Meu nome é Matheus Alberto e eu sou instrutor aqui na Alura.

Autodescrição: Homem branco de cabelos curtos lisos de cor castanho escuro. Tem o rosto oval, sobrancelhas grossas com um risco vertical na sobrancelha direita. Tem olhos castanho escuro e nariz e boca de tamanho médio. Está usando uma camiseta branca e sentado em uma cadeira de encosto alto na cor preta. No fundo há uma parede lisa com uma iluminação azul em um degradê da esquerda para direita de um tom de menor contraste para um de maior contraste.

O projeto

Vou apresentar para vocês o projeto que veremos no curso Flutter: Aplicando contraints e layouts responsivos. O projeto é o Panucci Ristorante.

Figma do projeto. Nele há o protótipo de 5 telas. Na primeira tela mostra um menu lateral sobreposto à tela do fundo. Na segunda tela temos o protótipo anterior com o menu fechado. No topo dela está a app bar com o ícone do menu, o texto "Ristorante Panucci" e o ícone do perfil. Em seguida há a seção dos "Destaques do dia" com três cartões quadrados grandes com a foto e as informações do prato. No meio do segundo cartão está a representação da bottom navigation bar com três ícones: o de "destaques", o "menu" e o "bebidas. O "Destaques" está selecionado. A terceira tela, abaixo da app bar tem uma lista com cartões menores, no formato de retângulos horizontais contendo menos informações do prato. Dessa forma cabem mais cartões listados na tela. No que será o canto inferior direito da tela, logo acima da navigation bar, tem um botão flutuante. Na navigation bar está selecionado o ícone "Menu". Na quarta tela estão as opções de bebidas em cartões quadrados pequenos, formando duas colunas. Ela também tem o botão flutuante no canto inferior direito e o ícone de "Bebidas" está selecionado na navigation bar. A quinta e última tela é a de checkout. Nela, abaixo da app bar tem a seção "Pedido", com cartões parecidos com os da seção de menu. A diferença é que na lateral direita tem a quantidade daquele item do cartão, que pode aumentar ou diminuir. Abaixo de "Pedido" tem seção "Pagamento", com as informações de pagamento, seguida da seção "Confirmar", com a revisão do pedido e, abaixo dela, o botão de "Pedir".

Esse é um aplicativo de cardápio onde a pessoa pode selecionar o que ela quer comer e beber e no final ela pode:

Em seguida viria um atendente que entregaria o pedido dessa pessoa.

O projeto que vamos desenvolver tem algumas coisas prontas. Então no projeto inicial já teremos as imagens que utilizaremos, as fontes e tipografias utilizadas, as cores do aplicativo já definidas e alguns widgets pré-montados. Os widgets são: os cartões de destaque, os cartões da seção "Menu", os cartões de bebida e os widgets das seções "Pedido", "Pagamento" e "Confirmar".

Com tudo isso, preencheremos as informações desses cartões no arquivo 'cardapio.dart". Nele temos as informações de cada lista do aplicativo, e usaremos essas informações para preencher nossa aplicação.

É muito importantes para fixarem o aprendizado desse curso que vocês façam todos os exercícios e que assista cada um dos vídeos com atenção. E qualquer dúvida que tiverem ao longo dos estudos, podem nos acionar no fórum do curso. Outro meio de comunicação é o discord da Alura, onde vocês podem tirar dúvidas, conversar com outras pessoas e saber dos novos conteúdos da nossa plataforma.

Vejo vocês no próximo vídeo e bons estudos

Iniciando o projeto - Conhecendo o projeto

Agora chegou nosso momento de começar a desenvolver nossa aplicação. Antes disso, vamos abrir o Figma do projeto e revisar do que temos que fazer. Observamos que temos 4 páginas para desenvolver.

A primeira delas é a página de Destaques. Nela constará os pedidos principais do dia, onde poderemos pedir algo especial. No parte superior da tela temos a App Bar (barra do app), seguida do título "Destaques do dia" e uma lista de cartões de pedido. Em cada cartão tem a imagem do prato, as informações de nome e preço, uma descrição breve e, no canto inferior direito do cartão, do botão de pedir.

Ao final da página temos a bottom navigation bar (barra inferior de navegação) com três páginas, inclusive as páginas extras que iremos montar. As páginas são "Destaques", "Menu" e "Bebidas".

A segunda tela que temos é a de Menu, com o app bar no topo, seguida do título "Menu" e uma lista com vários cartões. Nesses cartões têm as informações de título e valor do prato e uma imagem da comida no canto direito. No canto inferior direito da página, em cima da bottom navigation bar, tem um floating action button (botão de ação flutuante).

A próxima tela é a de Bebidas, onde temos novamente a App Bar, seguida do título "Bebidas", mas a lista está diferente. Ela não tem itens apenas na vertical, mas também na horizontal. Podemos chamar isso de Grid (Grade).

Então na tela Bebidas temos um grid de itens de bebidas. Os cartões desses itens possui uma imagem, o nome e o preço da bebida. Na parte inferior da tela temos a barra de navegação e o botão flutuante.

A quarta tela, que abrimos clicando no botão flutuante, é a tela de Checkout. Nela temos novamente a App Bar seguida do título da seção "Pedido", onde podemos rever o pedido feito através dos cartões dos itens. Cada cartão tem a imagem, o nome e o valor do prato, além de um contador na lateral direita para pessoa selecionar quanto daquele item ela quer.

Abaixo tem a seção "Pagamento", onde podemos selecionar o tipo de pagamento em outro widget de cartão. Em seguida temos a última seção, que é a "Confirmar", onde pode ser verificado o valor do pedido, da taxa de serviço e o total. Por fim, nesse tela temos o botão de "Pedir".

Antes de começarmos a codar, vamos analisar como está o nosso projeto dentro do VS Code. Grande parte do projeto, ou seja, as coisas que mais se repetem, como a estrutura dos cartões e a estrutura da aplicação, com o app bar e o bottom navigation bar, já estão prontas.

Portanto temos vários arquivos no nosso projeto. No Explorador, que fica na lateral esquerda do VS Code, temos a pasta "lib" contendo algumas pastas com arquivos de códigos prontos. A primeira pasta é a "components (componentes)" contendo os componentes que vimos, sendo eles:

O que precisaremos fazer é montar as telas e juntando as partes do app que já estão prontas. Inclusive, na pasta screens (telas)" temos o arquivo "home.dart" com a tela inicial completamente montada, que é para onde a pessoa será redirecionada ao abrir a aplicação.

Por fim, temos a pasta "themes (temas)", contendo o arquivo "app_colors.dart", com as cores utilizadas dentro do projeto. Se por algum motivo quiserem mudar as cores do projeto, basta abrir esse arquivo e alterar as cores pelas que vocês quiserem.

Como precisamos preencher os cartões dos itens com informações, temos um arquivo dentro da pasta "lib" chamado "cardapio.dart". Dentro dele estão todas as informações que usaremos para preencher os cartões. Um exemplo dos dados para um cartão:

  {
    "image": "$_imageInitialPath/chicken-salad.png",
    "name": "Chicken Salad",
    "price": "58.90",
    "description": "Experimente o maravilhoso chicken salad da casa com temperos inesquecíveis e um sabor de dar água na boca!"
  }

Então temos os caminhos das imagens, os nomes, os preços e a descrição de cada prato, isso para o menu de destaques, como no exemplo acima, com o código começando na linha 2. Para o menu de comidas, que começa na linha 41, temos os campos com os endereços da imagem, os nomes e os preços, como no exemplo abaixo.

  {
    "image": "$_imageInitialPath/chicken-tortilla.png",
    "name": "Chicken Tortilla",
    "price": "35.50"
  }

Também temos essas informações para o menu de bebidas (drinks), que começa na linha 94. Vejam um exemplo a seguir:

  {
    "image": "$_imageInitialPath/caipirinha.jpg",
    "name": "Caipirinha",
    "price": "12.00"
  }

Podemos, então acessar essas listas para obtermos essas informações.

Além disso, podemos acessar a pasta "assets > fonts" para acessarmos as fontes que usaremos no projeto, no caso a Caveat, como vemos no arquivo Caveat-Regular.ttf. Por fim, na pasta "assets > images" temos acesso aos arquivos de todas as imagens utilizadas no projeto.

Nosso próximo passo é juntar todas essas partes para começar a montar nossas telas.

Iniciando o projeto - Lista de produtos com ListView

Começaremos pela lista de destaque da página de "Destaques do dia". Para isso, voltaremos ao Figma do projeto para analisarmos as informações que vamos precisar.

Protótipo do Figma da página de destaques. No topo tem a App bar com o ícone do menu, o título "Ristorante Panucci" e o ícone do perfil do usuário. Abaixo tem o título da página, que é "Destaques do dia". Em seguida tem a lista de cartões com os pratos em destaque. No final da página está a bottom navigation bar.

Nessa tela temos o título da página e uma lista com vários cartões. Dentro dos cartões precisamos da imagem, do nome, do preço e da descrição do prato. Lembrando que todas essas informações estão dentro de um arquivo chamado "cardapio.dart".

Voltando para IDE, nosso primeiro passo será criar a lista de cartões. Como será uma tela nova, vamos clicar na pasta "screens" com o botão direito e selecionar "New File". O nome desse arquivo será "highlights.dart".

Ao pressionarmos "Enter" o arquivo é aberto, então podemos fechar o menu lateral para melhorar nossa visibilidade do código. Feito isso, vamos codar um widget de stateless básico. Para isso, podemos escrever fs e, no menu flutuante que surge, terá a opção "fstless". Selecionamos ela e, em seguida, importamos o StatelessWidget, usando atalhos do VS Code.

import 'package:flutter/material.dart';

class Highlights extends StatelessWidget {
const Highlights({ Key? key }) : super(key: key);

    @override
    Widget build(BuildContext context){
        return Container();
    }
}

Na linha 8, ao invés de return Container(), escreveremos return ListView.builder();. Com esse código conseguiremos montar uma lista a partir de outra lista. Assim conseguimos reunir esses itens e devolver uma informação para o Flutter montar na tela.

No caso, queremos usar os itens da lista destaques do arquivo "cardapio.dart". Além disso, vamos atribuir essa lista a uma variável para não a confundir no nosso código.

Então antes do @override, na linha 5, codaremos final List items = destaques;, fazendo um auto import de destaques. Sendo assim, se quisermos chamar a lista destaques, basta chamarmos pela variável items.

Dentro de ListView.builder, precisamos passaremos o itemBuilder, que é o que será retornado em cada item dentro da lista de itens. Vamos passar para ele um (context, index){}, que usaremos para saber a posição da lista que estamos acessando. Dentro da chaves passaremos o return.

import 'package:flutter/material.dart';

class Highlights extends StatelessWidget {
const Highlights({ Key? key }) : super(key: key);
    final List items = destaques;
    @override
    Widget build(BuildContext context){
        return ListView.builder(
            itemBuilder: (context, index) {
                return
            },
        );
    }
}

Nós já temos os componentes de destaque montados, então no retorno da linha 12 chamaremos esse componente, que é o HighlighItem():

//código omitido

                return HighlightItem(imageURI: imageURI, itemTitle: itemTitle, itemPrice: itemPrice, itemDescription: itemDescription;

Agora o VS Code está pedindo para preenchermos as informações do HighlightItem(), que são: o imageURI, itemTitle, itemPrice e itemDescription. Par passar essas informações, vamos chamar o items[index][], informando a posição do item da lista no primeiro colchetes e, depois, o parâmetro específico para o obtermos o dado.

Se voltarmos ao arquivo "cardapio.dart", observaremos que há uma lista de objetos e dentro de cada objeto existem algumas chaves. Para o imageURI precisaremos acessar a chave image, para o itemTitle precisaremos acessar o name, para o itemPrice precisamos do price e para o itemDescription precisamos da description. Sendo assim, preencheremos com essas informações.

//código omitido

        itemBuilder: (context, index) {
          return HighlightItem(imageURI: items[index]["image"], itemTitle: items[index]["name"], itemPrice: items[index]["price"], itemDescription: items[index]["description"]);
        },

Nosso código ainda não está completo, porque informamos o que será retornado, mas não quantos itens o ListView.builder precisa retornar. Para isso usaremos outra propriedade, que é o itemCount. Com o itemCount informamos o tamanho da lista que queremos inteirar. Faremos isso passando o valor items.lenght.

//código omitido

      return ListView.builder(
        itemBuilder: (context, index) {
          return HighlightItem(imageURI: items[index]["image"], itemTitle: items[index]["name"], itemPrice: items[index]["price"], itemDescription: items[index]["description"]);
        },
        itemCount: items.length,
      );

Após salvarmos esse arquivo, falta mostrarmos essas informações na tela. Para isso, acessaremos "lib > components > home.dart", que será a primeira página chamada assim que a aplicação abre.

Vamos rolar o código para o final e, após o fechamento do BottomNavigationBar, vamos escrever uma vírgula, pressionar "Enter" e escrever:

 body: Highlights(),

Ao salvarmos esse arquivo, no emulador aparece a lista com os pratos de destaque. Contudo, ao compararmos com o nosso design do Figma, reparamos que a imagem está bem maior do que deveria e está faltando o espaçamento da lista com a página.

Para fazermos o espaçamento, usaremos o Padding(). Então vamos retornar ao arquivo "highlights.dart", clicar em ListView.builder, abrir o menu de opções e selecionar a "Wrap with padding". Esse padding será de 16px, então na linha 11 mudaremos de .all(8.0) para .all(16.0):

//código omitido

  @override
  Widget build(BuildContext context){
    return Padding(
      padding: const EdgeInsets.all(16.0),
      child: ListView.builder(
        itemBuilder: (context, index) {
          return HighlightItem(imageURI: items[index]["image"], itemTitle: items[index]["name"], itemPrice: items[index]["price"], itemDescription: items[index]["description"]);
        },
        itemCount: items.length,
      ),
    );
  }

Dessa forma temos um espaçamento confortável entre os cartões e as margens, mas a imagem ainda está muito grande. Vamos descobrir como resolver isso no próximo vídeo.

Sobre o curso Flutter: aplicando constraints e implementando layouts responsivos

O curso Flutter: aplicando constraints e implementando layouts responsivos possui 130 minutos de vídeos, em um total de 48 atividades. Gostou? Conheça nossos outros cursos de Flutter em Mobile, ou leia nossos artigos de Mobile.

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

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

Conheça os Planos para Empresas