Fala, pessoal! Como estão? Hoje eu trago um tema super legal e bem importante para se pensar na hora de fazer nossos apps: os tamanhos relativos. Ou seja, fazer com que os elementos na sua tela não ocupem mais espaço do que a tela do dispositivo tenha disponível.

Criando projeto

Antes de mais nada, vamos criar um projeto bem básico para demonstrar com isso vai funcionar na prática. Só avisando que vou utilizar o Flutter na versão ‘2.2.1’ e o Dart na versão ‘2.13.3’.

O comando utilizado será:

flutter create tamanhos

Com o projeto criado, vamos abri-lo no VSCode ou em qualquer editor de sua preferência. Em seguida, basta abrir o arquivo main.dart e deixá-lo da seguinte maneira:

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Tamanhos',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      darkTheme: ThemeData.dark(),
      home: MyHomePage(title: 'Tamanhos'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Container(
              height: 50,
              width: 50,
              decoration: BoxDecoration(
                color: Colors.red,
              ),
            ),
          ],
        ),
      ),
    );
  }
}

Fiz o mínimo de alterações possíveis do arquivo criado por padrão, e adicionei um dark mode pra deixar tudo mais bonito, haha!

O resultado vai ser o seguinte:

É uma simples tela em branco, com um container super pequeno de 50×50 pixels na cor vermelha.

Tamanho absoluto

Quando falamos de tamanho absoluto, estamos falando de colocar os números exatos como tamanho de um widget. No container criado ali acima utilizei os tamanhos absolutos 50x50px para definir seu tamanho na tela. É bem difícil que esse tamanho gere erro em algum aparelho, afinal, hoje em dia, os celulares tem uma resolução bem alta. Mas caso a gente aumente esse tamanho, alterando o nosso Container para o seguinte:

						Container(
              height: 700,
              width: 400,
              decoration: BoxDecoration(
                color: Colors.blue,
              ),
            ),

Teremos como resultado o seguinte (troquei a cor apenas para indicar que mudamos o tamanho):

Com esse tamanho estamos ocupando uma boa porção da tela, mas ainda está tudo certo, sem nenhum problema acontecendo. Mas veja o que acontece se modificarmos novamente o container para o seguinte:

Container(
              height: 7000,
              width: 4000,
              decoration: BoxDecoration(
                color: Colors.blue,
              ),
            ),

O resultado no App é esse:

E o resultado log do VSCode é o seguinte:

Esse problema vai variar de dispositivo pra dispositivo. Mas em certo momento, em qualquer dispositivo os tamanhos absolutos vão gerar problema.

Tamanhos relativos

Para utilizar os tamanhos relativos, precisamos apenas de dois dados: o Height que se trata da altura; e o Width que é a largura da tela. Para isso, existe um código em Flutter que puxa os exatos tamanhos da tela aonde o código está rodando. O código é esse:

MediaQuery.of(context).size.height //para altura
MediaQuery.of(context).size.width //para largura

O resultado desse código é o tamanho da tela do dispositivo onde ele foi executado.

Para utilizar isso dentro do nosso projeto, nós vamos fazer da seguinte forma:

Container(
              height: MediaQuery.of(context).size.height * 0.3,
              width: MediaQuery.of(context).size.width * 0.3,
              decoration: BoxDecoration(
                color: Colors.green,
              ),
            ),

Como o resultado desse código se trata do tamanho inteiro da tela, o que precisa ser feito pra gente usar apenas uma fração da tela é multiplicar esse valor por algum valor entre 0 e 1. Ou seja, entre 0% e 100% do tamanho da tela. No caso do exemplo acima, eu utilizei o valor 0.3 que é referente a 30% dos tamanhos da altura e largura da tela do dispositivo.

O resultado desse código é o seguinte:

Existe uma forma de deixar esse código ainda mais limpo que é o seguinte: podemos puxar os valores do tamanho da tela lá em cima no código do projeto e armazenar os valores em variáveis para poder utilizar em qualquer ponto do código sem precisar digitar toda aquela linha. Isso pode ser feito dessa forma aqui:

final altura = MediaQuery.of(context).size.height;
final largura = MediaQuery.of(context).size.width;

Com esse código podemos utilizar apenas as variáveis altura e largura quando necessário. A localização desses trechos são logo acima do return do Scaffold principal e acima do Widget Build, assim:

Widget build(BuildContext context) {
    final altura = MediaQuery.of(context).size.height;
    final largura = MediaQuery.of(context).size.width;
    return Scaffold(
...

Com isso no código, podemos utilizar da seguinte forma:

Container(
              height: altura * 0.5,
              width: largura * 0.8,
              decoration: BoxDecoration(
                color: Colors.purple,
              ),
            ),

E o resultado é o seguinte:

Caso queiram, aqui está o código final do arquivo main.dart após todas as mudanças:

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Tamanhos',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      darkTheme: ThemeData.dark(),
      home: MyHomePage(title: 'Tamanhos'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    final altura = MediaQuery.of(context).size.height;
    final largura = MediaQuery.of(context).size.width;
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Container(
              height: altura * 0.5,
              width: largura * 0.8,
              decoration: BoxDecoration(
                color: Colors.purple,
              ),
            ),
          ],
        ),
      ),
    );
  }
}

Conclusão

Então é isso, galera. Fiquem de olho nessa questão, pois é algo super importante a se fazer com qualquer Widget para evitar problemas no seu projeto. Bons estudos, pessoal!