Olá Habr! Apresentando sua atenção a tradução do artigo "
Construindo layouts ".
Hoje descobrimos:
- Como os construtores de interface do usuário do Flutter funcionam
- Como fazer o layout das telas horizontal e verticalmente
- Como criar a tela usando o Flutter
O resultado da lição de hoje será o seguinte layout da tela
Etapa 0: Configuração do Projeto
Primeiro, crie um novo projeto File -> New Flutter Project -> next, next, next ...
Em seguida, crie o diretório images na raiz do projeto e coloque um arquivo chamado lake.jpg - você pode fazer o download do arquivo aqui -
linkTambém é necessário corrigir o arquivo de configuração pubspec.yaml (algo como gradle para android e cacau no iOS, podemos adicionar dependências externas nele). O texto do arquivo em si pode ser baixado
aqui.A fonte do projeto pode ser baixada
aqui - ela deve ser colocada no arquivo main.dart
Etapa 1: Gráfico da tela
Primeiro, divida o layout em elementos simples
- Definir linhas e colunas
- Determinar se o layout inclui uma grade?
- Existem elementos sobrepostos
- Preciso de guias para a interface do usuário?
- Preste atenção às áreas que requerem alinhamento ou recuo
Primeiro, identificamos os principais elementos grandes. Neste exemplo, 4 elementos são organizados em uma coluna: uma imagem, duas linhas e um bloco de teste

A seguir, analisaremos cada linha. A primeira linha, chamada “Título”, tem três filhos - uma coluna de texto, um ícone de estrela e um número. A primeira coluna contém 2 linhas. A primeira coluna ocupa muito espaço, portanto, você deve agrupá-la em um widget extensível.

A próxima linha, chamada de seção de botão, também tem 3 filhos. Cada um deles contém uma imagem e texto.

Finalmente, organizamos o layout em elementos simples. A maneira mais fácil de usar a abordagem "de baixo para cima" para o layout da tela. Para evitar uma estrutura complexa, divida a interface do usuário em variáveis e funções.
Etapa 2: criar uma linha de cabeçalhos
Primeiro, precisamos construir a coluna esquerda da seção do cabeçalho. Inserir uma coluna dentro de um widget extensível expande a coluna para usar todo o espaço restante na linha. Defina a propriedade crossAxisAlignment como CrossAxisAlignment.start para alinhar a coluna ao início da linha.
Colocar uma linha de texto dentro de um contêiner permite ativar o preenchimento. O segundo filho na coluna também é texto, está acinzentado. Os dois últimos elementos são marcados com o ícone "estrela" em vermelho e o texto com o valor "41". Coloque a linha inteira no contêiner e adicione recuo de 32 pixels em cada lado. O código para concluir essas etapas é apresentado abaixo.
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { Widget titleSection = Container( padding: const EdgeInsets.all(32.0), child: Row( children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( padding: const EdgeInsets.only(bottom: 8.0), child: Text( 'Oeschinen Lake Campground', style: TextStyle( fontWeight: FontWeight.bold, ), ), ), Text( 'Kandersteg, Switzerland', style: TextStyle( color: Colors.grey[500], ), ), ], ), ), Icon( Icons.star, color: Colors.red[500], ), Text('41'), ], ), ); //... }
Etapa 3: criar uma série de botões
A seção do botão consiste em 3 colunas, construídas de acordo com um princípio semelhante - um ícone acima de uma linha de texto. A coluna nesta linha é preenchida uniformemente e o texto e os ícones são desenhados na cor principal, que é selecionada como azul em nosso projeto no método build ().
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { //... return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), //... }
Como o código de construção de cada linha será quase idêntico, será mais eficaz usar uma função aninhada como buildButtonColumn (), que inclui um ícone e texto e retorna uma coluna com esse widget.
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { //... Column buildButtonColumn(IconData icon, String label) { Color color = Theme.of(context).primaryColor; return Column( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(icon, color: color), Container( margin: const EdgeInsets.only(top: 8.0), child: Text( label, style: TextStyle( fontSize: 12.0, fontWeight: FontWeight.w400, color: color, ), ), ), ], ); } //... }
A função de construção adiciona um ícone diretamente à coluna. Coloque o texto no recipiente para adicionar preenchimento e separe-o do ícone. Construímos cada linha dessas colunas chamando uma função e passando o ícone e o texto dentro da coluna. Alinhe a coluna ao longo do eixo principal usando MainAxisAlignment.spaceEvenly, organizando o espaço livre antes, entre e depois de cada coluna.
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { //... Widget buttonSection = Container( child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ buildButtonColumn(Icons.call, 'CALL'), buildButtonColumn(Icons.near_me, 'ROUTE'), buildButtonColumn(Icons.share, 'SHARE'), ], ), ); //... }
Etapa 4: criar a seção Descrição
Defina uma seção de descrição que é bastante longa. Coloque o texto no contêiner e adicione recuo de 32 pixels em cada borda.
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { //... Widget textSection = Container( padding: const EdgeInsets.all(32.0), child: Text( ''' Lake Oeschinen lies at the foot of the Blüemlisalp in the Bernese Alps. Situated 1,578 meters above sea level, it is one of the larger Alpine Lakes. A gondola ride from Kandersteg, followed by a half-hour walk through pastures and pine forest, leads you to the lake, which warms to 20 degrees Celsius in the summer. Activities enjoyed here include rowing, and riding the summer toboggan run. ''', softWrap: true, ), ); //... }
Etapa 5: criar a seção de imagem
Três das quatro colunas já foram construídas, resta apenas criar a coluna da imagem. A imagem usada neste projeto está disponível online sob a licença Creative Commons. Mas é grande e carregará lentamente. Na etapa 0, adicionamos uma imagem ao nosso projeto e atualizamos o arquivo de configuração, agora adicionaremos um link a ela em nosso código.
return MaterialApp( //... body: ListView( children: [ Image.asset( 'images/lake.jpg', height: 240.0, fit: BoxFit.cover, ), // ... ], ), //... );
BoxFit.cover informa à estrutura do Flutter que a imagem deve ser a menor possível, enquanto ainda cobre toda a área de renderização.
Etapa 6: Reunindo tudo
Na etapa final, coletaremos todas as partes do nosso código juntas. O widget está organizado em um ListView, não em uma coluna, porque o ListView rolará automaticamente enquanto estiver rolando em um dispositivo pequeno.
//... return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: Scaffold( appBar: AppBar( title: Text('Top Lakes'), ), body: ListView( children: [ Image.asset( 'images/lake.jpg', width: 600.0, height: 240.0, fit: BoxFit.cover, ), titleSection, buttonSection, textSection, ], ), ), ); //...