Expanded е Flutter widget, който принуждава дъщерния елемент да запълни цялото налично пространство във Flex контейнер. Когато Row или Column разпределят пространство между децата, Expanded взима свободното пространство след отчитане на нееластичните елементи. Според официалната документация на Flutter (2026), Expanded е един от най-използваните layout widgets: прилага се в процентното разпределение на интерфейси, изграждането на карти, списъци и панели. Основното му предимство е автоматичното изчисляване на ширина или височина на базата на flex коефициента без изрично посочване на размери.
Основни точки
Expanded е обвиващ widget, който приема child и го принуждава да се разшири, за да запълни наличното пространство във Flex контейнер (Row, Column, Flex). Expanded няма собствено визуално представяне — той само управлява ограниченията, предавани на дъщерния елемент.
В основата на Expanded стои механизмът Flex, предоставян от рамката Flutter. Когато Row или Column изчисляват размерите на своите деца, първо разпределят пространство на нееластични елементи (обикновени widgets с фиксирани размери), а останалото пространство разпределят между Expanded и Flexible деца пропорционално на техните flex фактори.
Expanded използва Flexible.fit = FlexFit.tight. Това означава, че детето на Expanded трябва да заеме цялото разпределено пространство, дори ако собственият му размер е по-малък. За разлика от Flexible с Fit.loose, където детето може да бъде по-малко от разпределената област, Expanded принудително разтяга съдържанието.
Заключение: Expanded е основният инструмент за създаване на пропорционални оформления във Flutter. Използвайте го, когато искате елемент гарантирано да заеме цялата налична ширина или височина.
Expanded и Flexible — и двата разпределят пространство във Flex контейнери, но се държат коренно различно. Разликата е в свойството fit, което определя дали детето може да бъде по-малко от наличното пространство.
Expanded има строг модел на поведение: неговото fit е равно на FlexFit.tight. Това означава, че дъщерният widget получава ограничения, равни на наличното пространство — нито повече, нито по-малко. Ако детето е по-малко, то се разтяга. Ако е по-голямо — се свива. Flexible използва FlexFit.loose, позволявайки на дъщерния елемент да бъде с произволен размер в рамките на разпределеното пространство.
На практика: ако вътре в Row има два Expanded с flex=1, всеки ще заеме точно половината от ширината. Ако ги замените с Flexible с fit.loose, всяко дете може да бъде по-малко от половината, ако собственият му размер е по-малък — останалото пространство ще остане празно.
Заключение: използвайте Expanded за строги пропорционални оформления, Flexible — когато детето може да бъде по-малко от наличното пространство. Ако не сте сигурни — започнете с Expanded, то дава по-предвидимо поведение.
Flex фактор (параметър flex) — числова стойност, определяща частта от наличното пространство, която ще получи Expanded. По подразбиране flex=1, което означава равномерно разпределение между всички Expanded деца.
Алгоритъмът за разпределение работи в три стъпки. Първа: Flutter изчислява intrinsic size на всички нееластични деца. Втора: останалото пространство се разделя на сумата от всички flex фактори. Трета: всеки Expanded получава част, равна на неговия flex фактор, умножен по размера на една flex единица.
Например, Row с ширина 300px съдържа два Expanded: първи с flex=2, втори с flex=1. Свободното пространство (300px минус нееластични деца) се разделя на 3 части. Първият получава 2/3, вторият — 1/3. Ако няма нееластични деца, първият ще получи 200px, вторият — 100px.
Flex фактор може да бъде всяко положително цяло число. Стойност 0 е специален случай: Expanded с flex=0 се държи като обикновен нееластичен widget, заемайки минимално пространство според размера на детето. Това поведение е еквивалентно на липса на 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('Област на съдържание'),
),
),
),
],
)
Вторият пример създава типично оформление със страничен панел (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”. Решение: проверявайте родителския widget — само Row, Column или Flex.
Грешка 2: поставяне на Expanded вътре в ListView без посочване на shrinkWrap. ListView по подразбиране има безкрайна височина в посоката на скролване и Expanded не може да изчисли своя дял. Решение: използвайте shrinkWrap: true или увийте ListView в SizedBox с фиксирана височина.
Грешка 3: няколко Expanded с общ flex, надвишаващ наличното пространство. Ако вътре в Row с ограничена ширина се намират Expanded, както и widgets с голям intrinsic size, може да възникне overflow. Решение: проверявайте минималните размери на нееластичните деца и при необходимост използвайте FittedBox или Flex fit.
Грешка 4: вложени Expanded в Column вътре в Row. Ако Expanded вътре в Column съдържа друг Expanded вътре в Row, може да възникне конфликт на ограничения. Решение: ограничавайте дълбочината на влагане или използвайте ConstrainedBox за изрично задаване на размери на междинни нива.
Заключение: Expanded изисква правилен родителски контекст. Винаги проверявайте, че Expanded се намира директно в Row, Column или Flex, и избягвайте влагане без изрични размери.
Често задавани въпроси
SizedBox.expand принудително разтяга детето до размерите, зададени от външни ограничения, но не участва във 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 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също