Expanded — віджет Flutter, який змушує дочірній елемент заповнювати весь доступний простір у Flex-контейнері. Коли Row або Column розподіляють місце між дітьми, Expanded забирає вільний простір після врахування негнучких елементів. За даними офіційної документації Flutter (2026), Expanded — один із найбільш використовуваних layout-віджетів: він застосовується у відсоткових інтерфейсах, побудові карток, списків та панелей. Головна його перевага — автоматичний розрахунок ширини або висоти на основі flex-коефіцієнта без явного вказання розмірів.
Головне
Expanded — це віджет-обгортка, який приймає дитину та змушує її розширюватися, щоб заповнити доступний простір у Flex-контейнері (Row, Column, Flex). Expanded не має власного візуального представлення — він лише керує обмеженнями (constraints), що передаються дочірньому елементу.
В основі Expanded лежить механізм Flex, який надається фреймворком Flutter. Коли Row або Column обчислюють розміри своїх дітей, вони спочатку виділяють місце негнучким елементам (звичайним віджетам з фіксованими розмірами), а решту простору розподіляють між Expanded та Flexible дітьми пропорційно їхнім flex-факторам.
Expanded використовує Flexible.fit = FlexFit.tight. Це означає, що дитина Expanded зобов'язана зайняти весь виділений їй простір, навіть якщо її власний розмір менший. На відміну від Flexible із Fit.loose, де дитина може бути меншою за виділену область, Expanded примусово розтягує вміст.
Висновок: Expanded — основний інструмент для створення пропорційних макетів у Flutter. Використовуйте його, коли потрібно, щоб елемент гарантовано зайняв всю доступну ширину або висоту.
Expanded та Flexible — обидва розподіляють простір у Flex-контейнерах, але поводяться принципово по-різному. Різниця полягає у властивості fit, яка визначає, чи може дитина бути меншою за доступне місце.
Expanded має жорстку модель поведінки: його fit дорівнює FlexFit.tight. Це означає, що дочірній віджет отримує обмеження, що дорівнюють доступному простору — ні більше, ні менше. Якщо дитина менша, вона розтягується. Якщо більша — вона стискається. Flexible використовує FlexFit.loose, дозволяючи дочірньому елементу бути будь-якого розміру в межах виділеного простору.
На практиці: якщо всередині Row знаходяться два Expanded з flex=1, кожен займе рівно половину ширини. Якщо замінити їх на Flexible з fit.loose, кожна дитина може бути меншою за половину, якщо її власний розмір менший — решта місця залишиться порожньою.
Висновок: використовуйте Expanded для строгих пропорційних макетів, Flexible — коли дитина може бути меншою за доступне місце. Якщо не впевнені — починайте з Expanded, воно дає більш передбачувану поведінку.
Flex-фактор (параметр flex) — числове значення, що визначає частку доступного простору, яку отримає Expanded. За замовчуванням flex=1, що означає рівномірний розподіл між усіма Expanded-дітьми.
Алгоритм розподілу працює в три кроки. Перший: Flutter обчислює внутрішній розмір усіх негнучких дітей. Другий: простір, що залишився, ділиться на суму всіх flex-факторів. Третій: кожен Expanded отримує частку, що дорівнює його flex-фактору, помноженому на розмір однієї одиниці flex.
Наприклад, Row шириною 300px містить два Expanded: перший з flex=2, другий з flex=1. Вільний простір (300px мінус негнучкі діти) ділиться на 3 частини. Перший отримує 2/3, другий — 1/3. Якщо негнучких дітей немає, перший отримає 200px, другий — 100px.
Flex-фактор може бути будь-яким додатним цілим числом. Значення 0 — особливий випадок: Expanded з flex=0 поводиться як звичайний негнучкий віджет, займаючи мінімальний простір за розміром дитини. Ця поведінка еквівалентна відсутності Expanded.
Висновок: flex-фактор — ключ до побудови гнучких макетів. Використовуйте співвідношення 1:1 для рівних колонок, 2:1 для панелей з основною та бічною областю, 3:1 для інтерфейсів з вузькою навігацією.
Приклад 1 демонструє базове використання Expanded у Row для створення трьох рівних колонок.
Row(
children: [
Expanded(
child: Container(
color: Colors.red,
),
),
Expanded(
child: Container(
color: Colors.green,
),
),
Expanded(
child: Container(
color: Colors.blue,
),
),
],
)
У цьому прикладі три Expanded з flex=1 (за замовчуванням) ділять ширину Row порівну. Контейнери розтягуються на всю висоту, задану Row, і займають рівні частки. Такий підхід зручний для створення колонкових макетів із пропорційним розподілом.
Приклад 2 показує використання різних flex-факторів для створення макету з бічною панеллю та основним вмістом.
Row(
children: [
Expanded(
flex: 1,
child: Container(
color: Colors.grey.200,
child: const Center(
child: Text('Бічна панель'),
),
),
),
Expanded(
flex: 3,
child: Container(
color: Colors.white,
child: const Center(
child: Text('Область вмісту'),
),
),
),
],
)
Другий приклад створює типовий layout з бічною панеллю (25%) та основною областю (75%). flex=1 та flex=3 дають співвідношення 1:3. При зміні ширини екрана пропорції зберігаються автоматично — це основа адаптивних інтерфейсів.
Висновок: Expanded з різними flex-факторами — стандартний інструмент для побудови адаптивних макетів. Поєднання Expanded у Column дозволяє створювати як горизонтальні, так і вертикальні пропорційні розкладки.
Помилка 1: використання Expanded поза Row, Column або Flex. Якщо помістити Expanded безпосередньо в Stack, ListView або інший контейнер, що не є Flex, Flutter викидає LayoutException з повідомленням «Expanded widgets must be placed inside Flex widgets». Рішення: перевіряти батьківський віджет — тільки Row, Column або Flex.
Помилка 2: розміщення Expanded всередині ListView без вказання shrinkWrap. ListView за замовчуванням має нескінченну висоту в напрямку прокручування, і Expanded не може розрахувати свою частку. Рішення: використовувати shrinkWrap: true або обертати ListView у SizedBox з фіксованою висотою.
Помилка 3: кілька Expanded із сумарним flex, що перевищує доступний простір. Якщо всередині Row з обмеженою шириною знаходяться Expanded, а також віджети з великим внутрішнім розміром, може виникнути overflow. Рішення: перевіряти мінімальні розміри негнучких дітей та при необхідності використовувати FittedBox або Flex fit.
Помилка 4: вкладені Expanded у Column всередині Row. Якщо Expanded всередині Column містить інший Expanded всередині Row, може виникнути конфлікт constraints. Рішення: обмежувати глибину вкладеності або використовувати ConstrainedBox для явного завдання розмірів на проміжних рівнях.
Висновок: Expanded вимагає правильного батьківського контексту. Завжди перевіряйте, що Expanded знаходиться безпосередньо в Row, Column або Flex, і уникайте вкладеності без явних розмірів.
Часті запитання
SizedBox.expand примусово розтягує дитину на розміри, задані зовнішніми constraints, але не бере участі у flex-розподілі. Expanded працює тільки всередині Flex-контейнерів і враховує flex-фактор при розподілі вільного простору між дітьми.
Ні. Stack не є Flex-контейнером, і використання Expanded всередині нього викличе LayoutException. Для розтягування дітей у Stack використовуйте Positioned.fill або BoxConstraints.expand.
За замовчуванням flex=1. Усі Expanded без явного flex отримають рівні частки вільного простору. Якщо в Row три Expanded без flex, кожен займе рівно третину доступного місця.
Помістіть Expanded у Row для розтягування по горизонталі. Для вертикального розтягування використовуйте Expanded всередині Column. Якщо потрібно обмежити розміри, оберніть Expanded або його дитину в SizedBox.
Expanded працює з Flex, включаючи Row та Column як його підкласи. Wrap не є Flex-контейнером і не підтримує Expanded. Для розподілу простору в Wrap використовуйте інші методи, наприклад RunAlignment.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також