> For the complete documentation index, see [llms.txt](https://dlyaverku.gitbook.io/flutter-dokumentaciya/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://dlyaverku.gitbook.io/flutter-dokumentaciya/osnovy-flutter/makety/pravila-komponovki-vo-flutter-kotorye-dolzhen-znat-kazhdyi.md).

# Правила компоновки во Flutter, которые должен знать каждый

Когда новичок во Flutter спрашивает, почему какой-то виджет с `width: 100` не ширины 100 пикселей, обычно ему отвечают, что надо обернуть этот виджет в `Center`, верно?

{% hint style="warning" %}
**Не надо так делать**
{% endhint %}

Если так отвечать, то к вам будут возвращаться снова и снова, спрашивая, почему какой-то `FittedBox` не работает, почему этот `Column` переполнен или как работает `IntrinsicWidth`.

Сначала объясните, что Flutter компоновка очень отличается от HTML компоновки (особенно, если говорите с веб-разработчиком), а затем скажите, что необходимо запомнить следующее правило:

> Ограничения для виджетов объявляются в родителях. Размеры *(желаемые)* задаются в самом виджете. Позиция виджета на экране устанавливается родителем

На мой взгляд, это правило нужно изучить, как можно раньше, так как без него по-настоящему понять компоновку во Flutter нельзя.

Более детально:

* Виджет получает свои **ограничения** от своего **родителя**. "Ограничение" — это всего 4 значения: минимальная и максимальная ширина, минимальная и максимальная высота.
* Затем виджет проходит по своему **списку детей**. Виджет сообщает своим дочерним элементам, каковы их **ограничения** (которые могут быть разными для каждого ребенка), а затем спрашивает каждого ребенка, какого размера он "хочет" быть.
* Затем виджет **размещает** свои **дочерние** элементы (горизонтально по оси x и вертикально по оси y) один за другим.
* И, наконец, виджет сообщает своему родителю о собственном **размере** (в пределах исходных ограничений, конечно).

Например, виджет, похожий на столбец с некоторыми отступами, хочет расположить два дочерних элемента:

![](/files/Z12WpSmTZrrCYfMpnwYH)

> **Виджет**: Родитель, каковы мои ограничения?\
> \
> **Родитель**: Ты должен быть от `90` до `300` пикселей в ширину и от `30` до `85` в высоту.\
> \
> **Виджет**: Хм, так как я хочу иметь 5 пикселей отступа, то мои дети могут иметь не более `290` пикселей ширины и `75` пикселей высоты.\
> \
> **Виджет**: Первый ребенок, вы должны быть от `0` до `290` пикселей в ширину и от `0` до `75` в высоту.\
> \
> **Первый ребенок**: Хорошо, тогда я хочу быть `290` пикселей в ширину и `20` пикселей в высоту.\
> \
> **Виджет**: Хм, поскольку я хочу поместить своего второго ребенка ниже первого, это оставляет только `55` пикселей высоты для моего второго ребенка.\
> \
> **Виджет**: Эй, второй ребенок, ты должен быть от `0` до `290` в ширину и от `0` до `55` в высоту.\
> \
> **Второй ребенок**: Хорошо, я хочу быть `140` пикселей в ширину и `30` пикселей в высоту.\
> \
> **Виджет**: Очень хорошо. Я расположу своего первого ребенка в точке `x: 5` и `y: 5`, а второго – в `x: 80` и `y: 25`.\
> \
> **Виджет**: Родитель, я решил, что мой размер будет `300` пикселей в ширину и `60` пикселей в высоту.

### Ограничения

В результате вышеописанного правила механизм компоновки Flutter имеет несколько важных ограничений:

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

### Примеры

Запустить CodePen ниже (сначала нужно нажать кнопку `Run Pen`, а затем кнопку `Rerun`, которая появится в правом нижнем углу экрана);

{% embed url="<https://codepen.io/marcglasberg/pen/ExVmwed>" %}

**Остальные примеры**

{% embed url="<https://habr.com/ru/post/500210>" %}
