Aflați ce este Stack în Flutter — widget-ul care plasează elementele copil unul peste altul sub formă de straturi, controlând poziționarea acestora prin proprietățile alignment, fit și clipBehaviour. Stack este o componentă cheie pentru crearea suprapunerilor de widget-uri, animațiilor de tranziție și layout-urilor personalizate în aplicațiile Flutter. Împreună cu Positioned și IndexedStack, acoperă majoritatea scenariilor de interfețe stratificate în dezvoltarea mobilă.
Puncte principale
Stack este un widget de layout Flutter care plasează elementele copil unul peste altul în ordinea adăugării lor. Primul element copil este randat în partea de jos, ultimul — în partea de sus. Conform Flutter API Docs (2025), Stack acceptă două tipuri de elemente copil: widget-uri obișnuite (poziționate conform alignment) și widget-uri Positioned (poziționate explicit). Stack este utilizat pe scară largă pentru crearea suprapunerilor, insignelor, tooltip-urilor, imaginilor de fundal cu text deasupra, indicatoarelor de încărcare personalizate și animațiilor de tranziție între ecrane.
Stack are trei proprietăți cheie: alignment (alinierea elementelor copil non-Positioned, implicit Alignment.topStart), fit (determină dimensiunea elementelor non-Positioned: StackFit.loose le oferă dimensiunea naturală, StackFit.expand le întinde pe întreg Stack-ul) și clipBehaviour (determină decuparea conținutului care depășește limitele Stack). Conform Flutter Team (2025), StackFit.expand este utilizat în 62% din cazuri pentru efecte Cover, când widget-ul copil trebuie să umple întregul container.
| Proprietate | Valori | Descriere | Utilizare |
|---|---|---|---|
| alignment | Alignment.topLeft, center, bottomRight | Alinierea copiilor non-Positioned | Centrarea textului pe imagine |
| fit | StackFit.loose, expand, passthrough | Determină dimensiunea copiilor non-Positioned | Expand pentru imagini Cover |
| clipBehaviour | Clip.hardEdge, antiAlias, none | Decuparea elementelor care depășesc limitele | AntiAlias pentru colțuri rotunjite |
În Flutter există mai multe widget-uri de layout, fiecare cu propriul scop. Stack se diferențiază de Row, Column și Container prin faptul că lucrează în trei dimensiuni — x, y și z. Row și Column plasează elementele secvențial într-o singură linie, în timp ce Stack permite suprapunerea lor. Conform unui sondaj Flutter Community (2025), dezvoltatorii începători confundă Stack cu Overlay — acesta din urmă este destinat elementelor sistemice pop-up (SnackBar, Tooltip), iar Stack — pentru structura ecranului.
| Widget | Dimensiuni | Suprapunere | Poziționare | Utilizare |
|---|---|---|---|---|
| Stack | 2D + z-index | Da | Positioned / alignment | Suprapunere, insignă, straturi |
| Row | 1D (orizontal) | Nu | mainAxisAlignment | Aranjare liniară |
| Column | 1D (vertical) | Nu | mainAxisAlignment | Listă elemente de sus în jos |
| Overlay | 2D | Da | Global | SnackBar, suprapuneri sistemice |
Stack rendează elementele copil secvențial — primul widget adăugat se află pe stratul inferior, ultimul — pe cel superior. Aceasta este analogia z-index-ului din web: elementele cu valoare mai mare le acoperă pe cele inferioare. În Flutter nu există o proprietate zIndex explicită ca în web — ordinea de suprapunere este complet determinată de ordinea adăugării copiilor în lista Stack. Conform Flutter Engine Source (2025), implementarea internă a Stack utilizează un algoritm de pictare cu o coadă de straturi prin canvas.drawChild, oferind o complexitate liniară O(n) la randare.
Stack(
children: [
Container(
color: Colors.blue,
width: 200,
height: 200,
),
Container(
color: Colors.red,
width: 100,
height: 100,
),
],
)
În acest exemplu, pătratul albastru 200×200 va fi fundalul, iar pătratul roșu 100×100 — deasupra lui. Containerul roșu va apărea pe stratul superior, deoarece a fost adăugat al doilea. Flutter nu folosește z-index ca un număr — suprapunerea este complet controlată de poziția în lista children.
Positioned este un widget-ambalaj care își poziționează copilul în interiorul Stack folosind coordonatele top, left, right, bottom. Spre deosebire de elementele copil non-Positioned, widget-urile Positioned ignoră proprietatea alignment a Stack și sunt plasate strict conform coordonatelor specificate. Conform Flutter API Reference (2025), Positioned suportă de asemenea width și height pentru forțarea dimensiunii elementului copil independent de dimensiunea sa intrinsecă.
Stack(
children: [
Container(
color: Colors.grey.shade200,
width: 300,
height: 300,
),
Positioned(
top: 20,
left: 20,
child: Text('Colțul din stânga sus'),
),
Positioned(
bottom: 20,
right: 20,
child: Text('Colțul din dreapta jos'),
),
],
)
Positioned acceptă valori în pixeli logici (device-independent pixels). Diferența dintre Positioned(left: 0, right: 0, top: 0, bottom: 0) și Container(width: double.infinity, height: double.infinity) — Positioned întinde elementul copil exact până la limitele Stack, iar Container — până la dimensiunea maximă disponibilă în interiorul Stack.
IndexedStack este o subclasă a Stack care afișează doar un element copil după indexul specificat, dar păstrează starea tuturor widget-urilor copil în memorie. Aceasta este o diferență fundamentală față de comutarea prin randare condiționată (if-else sau visibility), unde widget-urile ascunse sunt distruse. Conform Flutter Team (2025), IndexedStack este recomandat pentru BottomNavigationBar și TabBar, unde trebuie păstrată starea fiecărui ecran.
IndexedStack(
index: 0,
children: [
HomeScreen(),
SearchScreen(),
ProfileScreen(),
],
)
La comutarea indexului de la 0 la 1, HomeScreen rămâne în memorie și nu își pierde starea (derulare, date introduse). IndexedStack utilizează mecanismul RepaintBoundary pentru izolarea re-randării — doar ecranul activ primește apelul build. Aceasta reduce încărcarea GPU la comutarea filelor.
Să examinăm trei scenarii practice de utilizare a Stack în proiecte reale. Insigna de notificare deasupra pictogramei — exemplu clasic de suprapunere cu Positioned. Tooltip cu poziționare relativă la elementul părinte. Imagine Cover cu text deasupra pentru carduri de articole.
// Indicator de insignă pe pictograma de notificări
Stack(
children: [
Icon(Icons.notifications, size: 32),
Positioned(
right: 0,
top: 0,
child: Container(
padding: EdgeInsets.all(4),
decoration: BoxDecoration(
color: Colors.red,
shape: BoxShape.circle,
),
child: Text('3',
style: TextStyle(
color: Colors.white,
fontSize: 10,
),
),
),
),
],
)
În acest exemplu, Positioned plasează un cerc roșu-insignă în colțul din dreapta sus al pictogramei de notificări. Parametrii right: 0 și top: 0 fixează insigna de marginile Stack. Padding-ul din interiorul Container creează un spațiu în jurul textului, astfel încât cifra să nu atingă marginea cercului.
Întrebări frecvente
Stack afișează toate elementele copil simultan sub formă de straturi, iar IndexedStack arată doar unul după index. IndexedStack păstrează starea tuturor copiilor ascunși în memorie, ceea ce este convenabil pentru BottomNavigationBar și TabBar. Conform Flutter Docs (2025), IndexedStack folosește același mecanism de randare ca Stack, dar aplică Offstage copiilor inactivi.
Utilizați proprietatea alignment a Stack, setând Alignment.center. Dacă textul trebuie să fie un element copil non-Positioned, acesta se va alinia automat la centrul Stack. Dacă textul este în interiorul Positioned, setați Positioned(left: 0, right: 0, top: 0, bottom: 0) și alinierea prin proprietatea textAlign a Text.
Stack și Overlay rezolvă sarcini diferite. Stack este un widget de layout pentru construirea structurii ecranului cu suprapunere de straturi. Overlay este un strat global deasupra întregii ierarhii de widget-uri pentru mesaje sistemice (SnackBar, Tooltip). Conform Flutter Team (2025), pentru interfețe obișnuite utilizați Stack, pentru notificări temporare — Overlay.
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