Flexible — un widget Flutter care gestionează modul în care elementul copil ocupă spațiul disponibil într-un container Flex. Spre deosebire de Expanded, Flexible nu forțează copilul să umple întreaga zonă alocată — widgetul copil poate fi mai mic, iar spațiul rămas rămâne gol. Conform documentației oficiale Flutter (2026), Flexible este necesar în scenariile care necesită distribuirea flexibilă a spațiului fără întindere forțată: butoane cu lățime minimă, blocuri de text cu dimensiune naturală și elemente cu intrinsic constraints.
Principalele puncte
Flexible — este un widget-ambalaj care oferă elementului copil spațiu flexibil într-un container Flex. Flexible, ca și Expanded, participă la distribuirea spațiului liber, dar cu o diferență cheie: copilul Flexible poate ocupa mai puțin spațiu decât i s-a alocat, dacă dimensiunea sa proprie este mai mică decât spațiul disponibil.
Flexible utilizează algoritmul Flex al Flutter pentru a calcula spațiul disponibil. Mai întâi, framework-ul interoghează toți copiii neflexibili (widgeturi fără Flexible/Expanded) și calculează intrinsic size al acestora. Spațiul rămas este împărțit între copiii flexibili proporțional cu flex-factor al acestora. După alocarea spațiului, Flexible verifică fit — dacă este loose, se aplică copilului o constrângere „nu mai mult decât s-a alocat", permițându-i să rămână mic.
Particularitatea Flexible: dacă widgetul copil are propriile dimensiuni minime (de exemplu, Text cu un șir lung), Flexible alocă spațiul solicitat, nu îl întinde forțat. Acest lucru face Flexible de neînlocuit pentru elementele a căror dimensiune trebuie determinată de conținut, nu de container.
Concluzie: utilizați Flexible când trebuie să rezervați spațiu pentru un element, dar nu să îl forțați să se întindă. Aceasta păstrează dimensiunile naturale ale conținutului la distribuirea flexibilă a layout-ului.
FlexFit — o enumerare cu două valori: tight și loose. De alegerea fit depinde dacă widgetul copil va fi întins forțat la dimensiunile spațiului alocat.
FlexFit.tight: elementul copil primește tight constraints — dimensiunea minimă și maximă sunt egale cu spațiul alocat. Copilul trebuie să ocupe exact atât spațiu cât a alocat algoritmul Flex. Dacă copilul este mai mic — este întins. Dacă este mai mare — este comprimat. Comportament identic cu Expanded.
FlexFit.loose: elementul copil primește loose constraints — dimensiunea minimă este 0, maxima este egală cu spațiul alocat. Copilul poate fi de orice dimensiune de la 0 la maximum. Dacă copilul este mic (de exemplu, Text cu un șir scurt), ocupă lățimea sa naturală, iar restul spațiului rămâne gol.
Concluzie: FlexFit.loose — alegerea pentru blocuri de text și elemente cu dimensiune naturală. FlexFit.tight — pentru layout-uri stricte de coloană unde toate elementele trebuie să aibă aceeași lățime sau înălțime.
Flexible și Expanded arată similar, dar rezolvă sarcini diferite. Expanded întinde întotdeauna copilul pe întregul spațiu disponibil. Flexible poate lăsa spațiu gol în jurul copilului dacă dimensiunea conținutului este mai mică decât partea alocată.
Scenariul pentru Flexible: în interiorul Row se află două butoane. Primul — „Cumpără" (text scurt), al doilea — „Adaugă în coș" (text lung). Cu Expanded ambele butoane se vor întinde la aceeași lățime, iar textul scurt va avea margini uriașe. Cu Flexible fiecare buton va ocupa lățimea textului său, iar spațiul liber va rămâne între ele sau pe margini.
Scenariul pentru Expanded: în interiorul Column se află trei carduri care trebuie să aibă înălțime egală indiferent de conținut. Expanded împarte uniform înălțimea disponibilă și fiecare card se întinde la aceeași dimensiune. Flexible cu loose nu este potrivit aici — cardul mic va rămâne mic, încălcând designul unitar.
Concluzie: alegeți Flexible când conținutul determină dimensiunea elementului și spațiul gol în jurul lui este acceptabil. Alegeți Expanded când toate elementele trebuie să aibă aceeași dimensiune indiferent de conținut.
Exemplul 1 demonstrează utilizarea de bază a Flexible cu FlexFit.loose în Row.
Row(
children: [
Flexible(
fit: FlexFit.loose,
child: Container(
color: Colors.amber,
child: const Text('scurt'),
),
),
Flexible(
fit: FlexFit.loose,
child: Container(
color: Colors.cyan,
child: const Text('text lung pentru demo'),
),
),
],
)
În exemplu, ambele Flexible cu loose fit. Primul container cu text scurt ocupă lățimea sa naturală. Al doilea cu text lung — pe a sa. Row alocă fiecăruia jumătate din lățimea disponibilă, dar loose fit permite containerelor să fie mai mici, iar spațiul liber rămâne gol între ele.
Exemplul 2 — compararea Flexible cu Tight și Loose fit în Column.
Column(
children: [
Flexible(
fit: FlexFit.tight,
child: const Card(
child: ListTile(
title: Text('Tight — întins pe înălțime completă'),
),
),
),
const SizedBox(
height: 8,
),
Flexible(
fit: FlexFit.loose,
child: const Card(
child: ListTile(
title: Text('Loose — înălțime naturală'),
),
),
),
],
)
În Column, primul Flexible (tight) întinde Cardul pe jumătate din înălțimea disponibilă. Al doilea Flexible (loose) — Cardul ocupă înălțimea după conținut, iar restul spațiului rămâne gol. Vizual se vede cum tight umple forțat zona, iar loose păstrează dimensiunea compactă.
Concluzie: în codul de producție, Flexible cu loose se aplică pentru câmpuri de formular, butoane și blocuri de text. Flexible cu tight — echivalentul Expanded, utilizat pentru distribuire uniformă.
Eroarea 1: utilizarea Flexible în afara containerului Flex. Ca și Expanded, Flexible aruncă LayoutException dacă nu se află în interiorul Row, Column sau Flex. Soluție: verificați întotdeauna lanțul părinte al widgeturilor.
Eroarea 2: confuzia între Flexible și Expanded. Dezvoltatorii folosesc adesea Expanded când este necesar Flexible cu loose fit și invers. Rezultat: Expanded întinde elementul cu text scurt, creând câmpuri goale mari. Soluție: dacă dimensiunea elementului poate fi mai mică decât spațiul alocat — utilizați Flexible(fit: FlexFit.loose).
Eroarea 3: flex-factor zero. Flexible cu flex=0 se comportă ca un widget neflexibil, ceea ce poate fi neevident. Dezvoltatorul se așteaptă la un comportament flexibil, dar elementul ocupă dimensiunea minimă. Soluție: flex trebuie să fie ≥1 pentru distribuirea activă a spațiului.
Eroarea 4: Flexible în interiorul ScrollView fără limitare de dimensiune. Dacă Flexible se află în Column în interiorul SingleChildScrollView, containerul de scroll oferă spațiu infinit, iar distribuirea flex nu funcționează. Soluție: limitați dimensiunea containerului de scroll prin SizedBox sau ConstrainedBox.
Concluzie: Flexible necesită aceeași atenție la contextul părinte ca și Expanded. Diferența este doar în fit — alegeți-l conștient în funcție de sarcină.
Întrebări frecvente
Expanded — este Flexible cu fit=tight fix. Diferența constă în faptul că Expanded are o legătură rigidă la umplerea întregului spațiu disponibil, în timp ce Flexible poate folosi loose fit pentru a păstra dimensiunea naturală a copilului.
Pentru butoane cu lungimi diferite de text, utilizați Flexible(fit: FlexFit.loose). Fiecare buton va ocupa lățimea după conținut și nu va exista disproporție între ele. Expanded va face toate butoanele de aceeași lățime.
Setați fit: FlexFit.tight — Flexible va forța copilul să umple întregul spațiu alocat. În acest mod, Flexible este complet identic cu Expanded în comportament.
Da, dacă copilul este mai mare decât spațiul alocat. Flexible transmite constraints cu dimensiunea maximă egală cu partea containerului Flex. Dacă copilul depășește această dimensiune, el este comprimat în limitele constraints.
Da, Flexible funcționează cu orice container Flex, inclusiv Row, Column și widgetul de bază Flex cu direction arbitrară. Flex permite setarea direcțiilor nestandard prin mainAxisAlignment și crossAxisAlignment.
Concluzii
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și