Размер элементов в процентах от ширины / высоты экрана

155

Есть ли простой (не LayoutBuilder) способ размера элемента относительно размера экрана (ширина / высота)? Например: как мне установить ширину CardView равной 65% ширины экрана.

Это не может быть сделано внутри buildметода (очевидно), поэтому его придется отложить до пост-сборки. Есть ли предпочтительное место для такой логики?

Люк
источник
Просто скажу, что это вообще не очень хорошая практика IMO, это вещи веб-дизайна. В приложениях вы обычно должны использовать пиксели устройства для определения размеров и использовать отступы для вставки ваших виджетов, поскольку соотношение сторон почти всегда одинаково (за исключением планшетов).
leodriesch
8
Еще через 1,5 года кажется, что это не такая уж плохая идея. Каждый месяц появляются новые телефоны с более странным и более странным соотношением сторон.
Фарид

Ответы:

157

FractionallySizedBoxтакже может быть полезным. Вы также можете прочитать ширину экрана непосредственно MediaQuery.of(context).sizeи создать размерную коробку на основе этого

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

если вы действительно хотите, чтобы размер как часть экрана независимо от того, что макет.

Йен Хиксон
источник
204

Это дополнительный ответ, показывающий реализацию нескольких упомянутых решений.

FractionallySizedBox

Если у вас есть один виджет, вы можете использовать FractionallySizedBoxвиджет, чтобы указать процент доступного пространства для заполнения. Здесь зеленый цвет Containerзаполнен на 70% доступной ширины и 30% доступной высоты.

FractionallySizedBox

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

расширенный

ExpandedВиджет позволяет виджет , чтобы заполнить доступное пространство, в горизонтальном направлении, если он находится в ряде, или вертикально , если он находится в колонке. Вы можете использовать flexсвойство с несколькими виджетами, чтобы придать им вес. Здесь зеленый цвет Containerзанимает 70% ширины, а желтый - Container30% ширины.

расширенный

Если вы хотите сделать это вертикально, просто замените Rowна Column.

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

Дополнительный код

Вот main.dartкод для вашей справки.

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
источник
4
Вот как вы пишете ответ StackOverflow! Спасибо! Помог мне с моим Dialogстайлингом :)
Александар
117

Это может быть немного более понятно:

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

double yourWidth = width * 0.65;

Надеюсь, что это решило вашу проблему.

Кешав Адитья Р.П.
источник
16

Вы можете построить столбец / строку с гибкими или расширенными дочерними элементами, у которых есть значения flex, которые складываются в требуемые проценты.

Вы также можете найти виджет AspectRatio полезным.

Коллин Джексон
источник
9

Есть много способов сделать это

1. Использование MediaQuery: полный экран вашего устройства, включая панель приложений и панель инструментов.

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

введите описание изображения здесь


2. Используя Расширенное: Вы можете установить ширину / высоту в соотношении

 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],
              ),
            )
          ],
        ),
    )

введите описание изображения здесь



3. Другие, такие как Flexible и AspectRatio и FractionallySizedBox

Sanjayrajsinh
источник
7

вы можете использовать MediaQuery с текущим контекстом вашего виджета и получать ширину или высоту, как это double width = MediaQuery.of(context).size.width double height = MediaQuery.of(context).size.height после этого, вы можете умножить его на процент, который вы хотите

Parth Jansari
источник
7

Сначала получите размер экрана.

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

После этого вы можете получить widthи умножить его 0.5на 50% ширины экрана.

double width50 = size.width * 0.5;

Но проблема обычно возникает height, по умолчанию, когда мы используем

double screenHeight = size.height;

Высота, которую мы получаем, является глобальной высотой, которая включает в себя StatusBar+ notch+ AppBarвысоту. Итак, чтобы получить левую высоту устройства, нам нужно вычесть paddingвысоту ( StatusBar+ notch) и AppBarвысоту из общей высоты. Вот как мы это делаем.

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

Теперь мы можем использовать следующее, чтобы получить 50% высоты экрана.

double height50 = leftHeight * 0.5
CopsOnRoad
источник
3

если вы используете GridView, вы можете использовать что-то вроде решения Яна Хиксона.

crossAxisCount: MediaQuery.of(context).size.width <= 400.0 ? 3 : MediaQuery.of(context).size.width >= 1000.0 ? 5 : 4
Роди Дэвис
источник
2

Используйте виджет LayoutBuilder, который даст вам ограничения, которые вы можете использовать для получения высоты, исключающей AppBar и отступы. Затем используйте SizedBox и укажите ширину и высоту, используя ограничения из LayoutBuilder.

return LayoutBuilder(builder: (context2, constraints) {
  return Column(
    children: <Widget>[
      SizedBox(
        width: constraints.maxWidth,
        height: constraints.maxHeight,
        ...
никола
источник