Stack — ce este, straturi și poziționare în Flutter

Autor: IT Sectr Publicat: 2026-02-24 Timp de citire: 6 min

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 — widget Flutter care plasează elementele copil sub formă de straturi, suprapunându-le de-a lungul axei z.
  • Positioned permite setarea precisă a poziției elementului copil în interiorul Stack folosind top, left, right, bottom.
  • IndexedStack afișează doar un element copil după index, păstrând starea tuturor widget-urilor ascunse.
  • Stack suportă proprietățile alignment, fit (loose/passthrough/lavish) și clipBehaviour pentru controlul straturilor.
  • Conform datelor Google Flutter Team (2025), Stack este utilizat în 78% din aplicațiile Flutter din Google Play.

Ce este Stack în Flutter?

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.

Proprietățile principale ale Stack

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.

ProprietateValoriDescriereUtilizare
alignmentAlignment.topLeft, center, bottomRightAlinierea copiilor non-PositionedCentrarea textului pe imagine
fitStackFit.loose, expand, passthroughDetermină dimensiunea copiilor non-PositionedExpand pentru imagini Cover
clipBehaviourClip.hardEdge, antiAlias, noneDecuparea elementelor care depășesc limiteleAntiAlias pentru colțuri rotunjite

Compararea Stack cu alte widget-uri de layout Flutter

Î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.

WidgetDimensiuniSuprapunerePoziționareUtilizare
Stack2D + z-indexDaPositioned / alignmentSuprapunere, insignă, straturi
Row1D (orizontal)NumainAxisAlignmentAranjare liniară
Column1D (vertical)NumainAxisAlignmentListă elemente de sus în jos
Overlay2DDaGlobalSnackBar, suprapuneri sistemice

Cum funcționează Stack: straturi, z-index și ordinea de randare

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.

Dart
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: poziționare precisă în interiorul Stack

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ă.

Dart
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: comutarea între ecrane cu păstrarea stării

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.

Dart
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.

Exemple de cod: suprapunere widget-uri, insignă, tooltip

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.

Dart
// 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

Care este diferența dintre Stack și IndexedStack în Flutter?

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.

Cum se centrează textul în interiorul Stack?

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.

Ce este mai bun: Stack sau Overlay?

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

  • Stack — widget de layout Flutter pentru suprapunerea elementelor copil sub formă de straturi cu control prin alignment, fit și clipBehaviour.
  • Positioned setează coordonatele exacte ale elementului copil în interiorul Stack după top, left, right, bottom.
  • IndexedStack afișează un element după index, păstrând starea tuturor widget-urilor ascunse.
  • Z-index este determinat de ordinea adăugării copiilor: ultimul element este randat deasupra.
  • Stack este utilizat în 78% din aplicațiile Flutter pentru insignă, tooltip, conținut Cover și animații.
  • Utilizați Stack la necesitatea suprapunerii elementelor, Overlay — pentru notificări sistemice.

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.

Discutați proiectul

Citiți și