Neste artigo, vamos aprender algumas das abordagens e widgets que são usados na construção de layouts responsivo no Flutter.
Quando falamos em responsividade, significa dizer que o conteúdo ou o layout deve ser flexível para caber em diferentes tamanhos de tela as quais a aplicação será exibida.
Um dos principais objetivos do Flutter é criar uma estrutura que permita desenvolver aplicativos a partir de uma única base de código. Isso significa que seu aplicativo pode aparecer em telas de diferentes dimensões.
Não há uma regra para projetar um layout responsivo em Flutter, o mesmo disponibiliza diversas maneiras para se alcançar tal objetivo e cada uma é mais indicada para um determinado contexto, o importante é conhecer quais são essas maneiras e como as mesmas funcionam.
A diferença entre um aplicativo adaptativo e um responsivo
Em primeiro lugar, adaptável e responsivo podem ser vistos como dimensões separadas de um aplicativo. Você pode ter um aplicativo adaptativo que não seja responsivo, ou vice-versa. E, claro, um aplicativo pode ser ambos, ou nenhum dos dois.
Normalmente, um aplicativo responsivo deve ter seu layout sintonizado para o tamanho da tela disponível. Por exemplo, se o usuário redimensionar a janela ou mudar a orientação do dispositivo.
Contudo, adaptar um aplicativo para ser executado em diferentes tipos de dispositivos, como celular e desktop, requer lidar com a entrada de mouse e do teclado, bem como entrada de toque. Por exemplo, uma tela que ao scrollar arrastando o dedo no touch screen também deve responder ao scrollar do mouse.
Curso Flutter - Fundamentos
Conhecer o cursoComo construir um layout Flutter responsivo
Antes de mais nada, o Flutter permite criar aplicativos que se auto ajustam para diferentes tamanhos e orientações da tela do dispositivo.
Para que isso seja possível, temos diversos widgets que vão nos ajudar no desenvolvimento de aplicativos responsivos.
Alguns widgets e classes úteis para criar uma interface do usuário responsiva são:
- AspecRatio
- CustomSingleChildLayout
- CustomMultiChildLayout
- FittedBox
- FractionallySizedBox
- MediaQuery
- MediaQueryData
Agora, vamos ver alguns exemplos de como utilizar esses widgets.
OrientationBuilder
O widget OrientationBuilder
permite que você modifique seu layout para responder de acordo com a orientação do dispositivo.
OrientationBuilder(
builder: (context, orientation) {
return GridView.count(
crossAxisCount: orientation == Orientation.portrait ? 2 : 4,
mainAxisSpacing: 10,
crossAxisSpacing: 10,
children: List.generate(
50,
(index) => Container(
color: Colors.grey,
child: Text(
"$index",
style: const TextStyle(fontSize: 32),
),
),
),
);
},
);
Assim como mostrado neste exemplo o OrientationBuilder
tem um builder que passa o context
e o orientation
, os quais podemos utilizar para saber em qual tipo de orientação o dispositivo se encontra.
Sendo assim dependendo da orientação em que o dispositivo estiver nosso layout irá se organizar em duas ou quatro colunas.
Confira mais detalhes na Documentação do OrientationBuilder
Curso Dart - Fundamentos
Conhecer o cursoLayoutBuilder
De acordo com a documentação do Flutter o LayoutBuilder
é um widget que consegue passar o tamanho onde ele se encontra na arvore de widgets.
@override
Widget build(BuildContext context) {
const percent = 3;
return Scaffold(
body: LayoutBuilder(
builder: (context, constrains) {
return Column(
children: [
Container(
width: constrains.maxWidth,
height: constrains.maxHeight / percent,
color: Colors.red,
),
Container(
width: constrains.maxWidth,
height: constrains.maxHeight / percent,
color: Colors.blue,
),
Container(
width: constrains.maxWidth,
height: constrains.maxHeight / percent,
color: Colors.green,
),
],
);
},
),
);
}
O LayoutBuilder
passa um builder, que é uma função, passando o context
e as constrains
.
As constrains
são exatamente onde conseguimos pegar o tamanho e fazer um cálculo simples para que todos os conteúdos filhos possam caber corretamente na tela. Ou seja, como resultado teremos containers que vão se adaptar independentemente do tamanho da tela.
Confira mais detalhes na Documentação do LayoutBuilder
Flexible e Expanded
Também temos os widgets Flexible
e Expanded
para nos ajudar na construção de layouts Flutter responsivos.
O widgets Expanded
e Flexible
funcionam de maneira semelhante, ambos vão preencher todo o conteúdo disponível da tela. Porém, o Flexible
permite que você respeite o tamanho do widget filho enquanto o Expanded
não.
Column(
children: [
Flexible(
child: Container(
color: Colors.blue,
),
),
Flexible(
flex: 3,
child: Container(
color: Colors.green,
),
),
Flexible(
child: Container(
height: 100,
color: Colors.red,
),
),
],
);
Desse modo mostrado no exemplo todos os filhos do Flexible
vão tentar ocupar o maximo de espaços possível.
Curso Flutter - Fundamentos
Conhecer o cursoComponentes
Usando uma abordagem de componentização, podemos extrair sua lógica do layout em componentes separados para que, ao projetar layouts em uma tela grande, você não precisa definir a lógica separadamente. Sendo assim podemos apenas reutilizar a lógica que foi definido para cada fragmento.
Vamos utilizar como exemplo o código desenvolvido no artigo Criando um BottomNavigationBar com Flutter, porém o fragmentando em um componente para melhor reaproveitamento.
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: Scaffold(
bottomNavigationBar: CustomAppBar(),
),
);
}
}
class CustomAppBar extends StatelessWidget {
const CustomAppBar({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return OrientationBuilder(
builder: (context, orientation) {
final isPortrait = orientation == Orientation.portrait;
return BottomNavigationBar(
items: [
BottomNavigationBarItem(
icon: const Icon(Icons.person),
label: "Minha conta",
activeIcon:
isPortrait ? null : const Text('Configurações da conta'),
),
BottomNavigationBarItem(
icon: const Icon(Icons.shopping_basket),
label: "Meus pedidos",
activeIcon: isPortrait
? null
: const Text('Carrinho de Compras e seus pedidos'),
),
BottomNavigationBarItem(
icon: const Icon(Icons.favorite),
label: "Favoritos",
activeIcon:
isPortrait ? null : const Text('Itens Favoritos do carrinho'),
),
],
);
},
);
}
}
Gráficos vetoriais
Ao contrário de serem criados usando bitmaps de pixel, gráficos vetoriais são imagens definidas em arquivos XML como caminhos e cores. Sendo assim eles podem escalar para qualquer tamanho sem perder a qualidade da imagem.
Caso queira aprender mais sobre imagens vetoriais leia o artigo O que são imagens vetoriais.
Conclusão
Criar um aplicativo totalmente responsivo em Flutter é um desafio, porém, como vimos neste artigo há uma série de widgets que podemos usar para nós auxiliar nesta tarefa.
Além disso, existem plugins que também possuem o intuito de facilitar a vida que quem desenvolve aplicativos responsivos com Flutter, alguns deles são:
Por fim, caso queira aprender mais sobre Flutter e sua infinidade de recursos saiba que aqui na Treinaweb temos o curso Flutter - Fundamentos que possui 01h54 de vídeo e um total de 11 exercícios. Conheça também nossos outros cursos de Flutter.
Veja quais são os tópicos abordados durante o curso de Flutter - Fundamentos:
- Como configurar seu ambiente de desenvolvimento;
- O que são e como funcionam os widgets;
- O que são os widgets stateful e stateless;
- Como funciona a hierarquia de interfaces do Flutter;
- Como trabalhar com estados em nosso app;
- Como validar formulários com o Flutter.