Dimensionando elementos para porcentagem da largura / altura da tela

153

Existe uma maneira simples (não-LayoutBuilder) de dimensionar um elemento em relação ao tamanho da tela (largura / altura)? Por exemplo: como faço para definir a largura de um CardView como 65% da largura da tela.

Isso não pode ser feito dentro do buildmétodo (obviamente), portanto, teria que ser adiado até a pós-compilação. Existe um lugar preferido para colocar uma lógica como essa?

Lucas
fonte
Apenas dizendo, isso geralmente não é uma boa prática IMO, isso é coisa de design da web. Nos aplicativos, geralmente você deve usar pixels do dispositivo para definir tamanhos e usar Paddings para inserir seus widgets, pois a proporção é quase sempre a mesma (exceto para tablets).
leodriesch 18/02/19
7
Depois de mais de 1,5 anos, parece que essa não é uma idéia tão ruim, afinal. Todo mês há novos telefones sendo lançados com uma proporção cada vez mais estranha.
Farid

Respostas:

156

FractionallySizedBoxtambém pode ser útil. Você também pode ler a largura da tela diretamente MediaQuery.of(context).sizee criar uma caixa de tamanho com base nessa

MediaQuery.of(context).size.width * 0.65

se você realmente deseja dimensionar como uma fração da tela, independentemente do layout.

Ian Hickson
fonte
202

Esta é uma resposta suplementar, mostrando a implementação de algumas das soluções mencionadas.

FractionallySizedBox

Se você tiver um único widget, poderá usá-lo FractionallySizedBoxpara especificar uma porcentagem do espaço disponível para preencher. Aqui, o verde Containeré definido para preencher 70% da largura disponível e 30% da altura disponível.

FractionallySizedBox

Widget myWidget() {
  return FractionallySizedBox(
    widthFactor: 0.7,
    heightFactor: 0.3,
    child: Container(
      color: Colors.green,
    ),
  );
}

Expandido

O Expandedwidget permite que ele preencha o espaço disponível, horizontalmente, se estiver em uma linha, ou verticalmente, se estiver em uma coluna. Você pode usar a flexpropriedade com vários widgets para fornecer pesos a eles. Aqui, o verde Containerocupa 70% da largura e o amarelo Containerocupa 30% da largura.

Expandido

Se você quiser fazer isso verticalmente, substitua-o Rowpor Column.

Widget myWidget() {
  return Row(
    children: <Widget>[
      Expanded(
        flex: 7,
        child: Container(
          color: Colors.green,
        ),
      ),
      Expanded(
        flex: 3,
        child: Container(
          color: Colors.yellow,
        ),
      ),
    ],
  );
}

Código suplementar

Aqui está o main.dartcódigo para sua referência.

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text("FractionallySizedBox"),
        ),
        body: myWidget(),
      ),
    );
  }
}

// replace with example code above
Widget myWidget() {
  return ...
}
Suragch
fonte
4
É assim que você escreve uma resposta do StackOverflow! Obrigado! Ajudou-me com o meu Dialogestilo :)
Aleksandar
116

Isso pode ser um pouco mais claro:

double width = MediaQuery.of(context).size.width;

double yourWidth = width * 0.65;

Espero que isso tenha resolvido o seu problema.

Keshav Aditya RP
fonte
16

Você pode criar uma coluna / linha com filhos flexíveis ou expandidos que tenham valores flexíveis que somam as porcentagens desejadas.

Você também pode achar útil o widget AspectRatio .

Collin Jackson
fonte
9
MediaQuery.of(context).size.width
Nitin Mehta
fonte
9

Há muitas maneiras de fazer isso

1. Usando o MediaQuery: retorna a tela cheia do seu dispositivo, incluindo barra de aplicativos, barra de ferramentas

 Container(
        width: MediaQuery.of(context).size.width * 0.50,
        height: MediaQuery.of(context).size.height*0.50, 
        color: Colors.blueAccent[400],
 )

insira a descrição da imagem aqui


2. Usando o Expanded: você pode definir a largura / altura na proporção

 Container(
        height: MediaQuery.of(context).size.height * 0.50,
        child: Row(
          children: <Widget>[
            Expanded(
              flex: 70,
              child: Container(
                color: Colors.lightBlue[400],
              ),
            ),
            Expanded(
              flex: 30,
              child: Container(
                color: Colors.deepPurple[800],
              ),
            )
          ],
        ),
    )

insira a descrição da imagem aqui



3. Outros, como Flexible e AspectRatio e FractionallySizedBox

Sanjayrajsinh
fonte
7

você pode usar o MediaQuery com o contexto atual do seu widget e obter largura ou altura assim, double width = MediaQuery.of(context).size.width double height = MediaQuery.of(context).size.height depois disso, pode multiplicá-lo pela porcentagem desejada

parth jansari
fonte
7

Primeiro obtenha o tamanho da tela.

Size size = MediaQuery.of(context).size;

Depois disso, você pode obtê width-lo e multiplicá-lo 0.5para obter 50% da largura da tela.

double width50 = size.width * 0.5;

Mas o problema geralmente aparece height, por padrão, quando usamos

double screenHeight = size.height;

A altura que obtemos é a altura global, que inclui StatusBar+ notch+ AppBaraltura. Portanto, para obter a altura esquerda do dispositivo, precisamos subtrair a paddingaltura ( StatusBar+ notch) e a AppBaraltura da altura total. Aqui está como fazemos.

double abovePadding = MediaQuery.of(context).padding.top;
double appBarHeight = appBar.preferredSize.height;
double leftHeight = screenHeight - abovePadding - appBarHeight;

Agora podemos usar o seguinte para obter 50% da nossa tela em altura.

double height50 = leftHeight * 0.5
CopsOnRoad
fonte
3

se você estiver usando o GridView, poderá usar algo como a solução de Ian Hickson.

crossAxisCount: MediaQuery.of(context).size.width <= 400.0 ? 3 : MediaQuery.of(context).size.width >= 1000.0 ? 5 : 4
Rody Davis
fonte
2

Use o Widget LayoutBuilder que fornecerá restrições que você pode usar para obter a altura que exclui o AppBar e o preenchimento. Em seguida, use uma SizedBox e forneça a largura e a altura usando as restrições do LayoutBuilder

return LayoutBuilder(builder: (context2, constraints) {
  return Column(
    children: <Widget>[
      SizedBox(
        width: constraints.maxWidth,
        height: constraints.maxHeight,
        ...
Nicolas
fonte