No history yet

Архітектура віджетів та Layout

Правила гри у Flutter Layout

В основі механізму розмітки Flutter лежить просте, але потужне правило, яке керує кожним пікселем на екрані: «Обмеження спускаються вниз, розміри підіймаються вгору, батьки визначають позицію».

Уявіть це як розмову між віджетами. Батьківський віджет каже своєму дочірньому: «Ось стільки місця ти можеш зайняти». Це і є обмеження (constraints). Дочірній віджет, отримавши ці правила, вирішує, яким буде його фактичний розмір, і повідомляє про це батькові. Нарешті, батько, знаючи розмір дочірнього елемента, розміщує його у себе.

Цей односпрямований потік даних робить систему розмітки Flutter дуже передбачуваною та ефективною. Віджет може впливати лише на своїх нащадків, а не на батьків чи сусідів.

Жорсткі та вільні обмеження

Обмеження у Flutter, які передаються через об'єкт BoxConstraints, бувають двох основних типів: жорсткі (tight) та вільні (loose).

Жорсткі обмеження не залишають віджету вибору. Вони задають точну ширину і висоту, встановлюючи однакові мінімальні та максимальні значення. Наприклад, віджет SizedBox(width: 100, height: 100) передає своєму нащадку жорстке обмеження 100×100100 \times 100 пікселів.

Вільні обмеження, навпаки, дають віджету свободу. Вони визначають максимальну ширину та висоту, але мінімальні значення дорівнюють нулю. Це дозволяє дочірньому елементу бути настільки малим, наскільки він хоче, але не більшим за вказані межі. Класичний приклад — віджет Center, який передає своєму нащадку вільні обмеження, що відповідають розмірам самого Center.

Розуміння різниці між цими типами обмежень є ключовим для уникнення поширених помилок розмітки, таких як нескінченна ширина Row або невидимі елементи.

Адаптивні та кастомні Layouts

Що робити, коли стандартних віджетів недостатньо або потрібно створити інтерфейс, що адаптується до різних розмірів екрана? Flutter надає для цього потужні інструменти.

LayoutBuilder

noun

Віджет, який будує дерево віджетів, що може залежати від розміру батьківського віджета. Він надає доступ до об'єкта BoxConstraints батька.

LayoutBuilder є ідеальним рішенням для створення адаптивних інтерфейсів. Він не впливає на розмітку сам по собі, а лише «підслуховує» обмеження від батька і передає їх у свою функцію-конструктор. Це дозволяє вам динамічно змінювати UI залежно від доступного простору.

LayoutBuilder(
  builder: (BuildContext context, BoxConstraints constraints) {
    if (constraints.maxWidth > 600) {
      // Для широких екранів
      return TwoColumnsLayout();
    } else {
      // Для вузьких екранів
      return OneColumnLayout();
    }
  },
)

Для ще більш складних сценаріїв існують CustomSingleChildLayout та CustomMultiChildLayout. Ці віджети дають вам повний контроль над розміщенням та розмірами одного або кількох дочірніх елементів. Ви самостійно визначаєте логіку в спеціальному класі-делегаті, що дозволяє створювати унікальні компонування, наприклад, кругове меню або діагональний список.

Оптимізація розмітки

Іноді батьківському віджету потрібно знати «природний» розмір дочірнього елемента, перш ніж встановлювати фінальні обмеження. Для цього існують віджети IntrinsicHeight та IntrinsicWidth.

Наприклад, IntrinsicHeight змушує всіх нащадків у Row мати однакову висоту, що дорівнює висоті найвищого з них. Це може бути корисно для вирівнювання елементів, але має свою ціну. Обчислення внутрішніх розмірів є ресурсомісткою операцією, оскільки вимагає додаткового проходу по дереву віджетів. Використовуйте ці віджети обережно і лише тоді, коли інші, більш прості рішення, не підходять.

Найкраща оптимізація — це найпростіша розмітка. Намагайтеся створювати гнучкі UI, які добре виглядають при різних розмірах, замість того, щоб змушувати їх мати один конкретний розмір.

Тепер, коли ви розумієте ключові принципи розмітки у Flutter, давайте перевіримо ваші знання.

Quiz Questions 1/5

Яке з цих тверджень найкраще описує основне правило механізму розмітки у Flutter?

Quiz Questions 2/5

Що таке «жорсткі» (tight) обмеження у Flutter?

Опанувавши ці концепції, ви готові створювати складні, адаптивні та оптимізовані інтерфейси, які працюють передбачувано на будь-якому пристрої.