Сазнајте шта је Stack у Flutter-у — виџет који поставља елементе један изнад другог у виду слојева, управљајући њиховим позиционирањем кроз својства alignment, fit и clipBehaviour. Stack је кључна компонента за креирање преклапања виџета, анимација прелаза и прилагођених распореда у Flutter апликацијама. Заједно са Positioned и IndexedStack покрива већину сценарија слојевитих интерфејса у мобилном развоју.
Главно
Stack је виџет за распоред у Flutter-у који поставља елементе један изнад другог редом њиховог додавања. Први елемент се црта на дну, последњи — на врху. Према Flutter API Docs (2025), Stack прихвата две врсте елемената: обичне виџете (позициониране према alignment-у) и Positioned виџете (експлицитно позициониране). Stack се широко користи за креирање преклапања, значки, описа, позадинских слика са текстом изнад, прилагођених индикатора учитавања и анимација прелаза између екрана.
Stack има три кључна својства: alignment (поравнање не-Positioned елемената, подразумевано Alignment.topStart), fit (одређује величину не-Positioned елемената: StackFit.loose даје природну величину, StackFit.expand их развлачи на цео Stack) и clipBehaviour (одређује обрезивање садржаја који излази из граница Stack-а). Према Flutter Team (2025), StackFit.expand се користи у 62% случајева за Cover ефекте, када виџет треба да испуни цео контејнер.
| Својство | Вредности | Опис | Примена |
|---|---|---|---|
| alignment | Alignment.topLeft, center, bottomRight | Поравнање не-Positioned елемената | Центрирање текста изнад слике |
| fit | StackFit.loose, expand, passthrough | Одређује величину не-Positioned елемената | Expand за Cover слике |
| clipBehaviour | Clip.hardEdge, antiAlias, none | Обрезивање елемената који излазе из граница | AntiAlias за заобљене углове |
У Flutter-у постоји неколико виџета за распоред, сваки са својом наменом. Stack се разликује од Row, Column и Container по томе што ради у три димензије — x, y и z. Row и Column постављају елементе секвенцијално у једну линију, док Stack омогућава њихово преклапање. Према анкети Flutter Community (2025), почетници програмери мешају Stack и Overlay —后者 је намењен за системске искачуће елементе (SnackBar, Tooltip), а Stack — за структуру екрана.
| Виџет | Димензије | Преклапање | Позиционирање | Употреба |
|---|---|---|---|---|
| Stack | 2D + z-index | Да | Positioned / alignment | Преклапање, значке, слојеви |
| Row | 1D (хоризонтално) | Не | mainAxisAlignment | Линеарни распоред |
| Column | 1D (вертикално) | Не | mainAxisAlignment | Листа елемената одозго надоле |
| Overlay | 2D | Да | Глобално | SnackBar, системски оверлеји |
Stack црта елементе секвенцијално — први додати виџет налази се на доњем слоју, последњи — на горњем. Ово је аналогно z-индексу на вебу: елементи са вишом вредношћу прекривају ниже. У Flutter-у не постоји експлицитно својство zIndex као на вебу — редослед преклапања је потпуно одређен редом додавања деце у листу Stack-а. Према Flutter Engine Source (2025), унутрашња имплементација Stack-а користи алгоритам сликара са редом слојева кроз canvas.drawChild, што даје линеарну сложеност O(n) при цртању.
Stack(
children: [
Container(
color: Colors.blue,
width: 200,
height: 200,
),
Container(
color: Colors.red,
width: 100,
height: 100,
),
],
)
У овом примеру плави квадрат 200×200 биће позадина, а црвени квадрат 100×100 — изнад њега. Црвени контејнер појавиће се на горњем слоју, јер је додат као други. Flutter не користи z-index као број — преклапање је потпуно контролисано позицијом у листи children.
Positioned је виџет-омотач који позиционира свог потомка унутар Stack-а помоћу координата top, left, right, bottom. За разлику од не-Positioned елемената, Positioned виџети игноришу својство alignment Stack-а и постављају се строго према датим координатама. Према Flutter API Reference (2025), Positioned такође подржава width и height за принудно одређивање величине елемента независно од његове природне величине.
Stack(
children: [
Container(
color: Colors.grey.shade200,
width: 300,
height: 300,
),
Positioned(
top: 20,
left: 20,
child: Text('Горњи леви угао'),
),
Positioned(
bottom: 20,
right: 20,
child: Text('Доњи десни угао'),
),
],
)
Positioned прихвата вредности у логичким пикселима (device-independent pixels). Разлика између Positioned(left: 0, right: 0, top: 0, bottom: 0) и Container(width: double.infinity, height: double.infinity) — Positioned развлачи елемент тачно до граница Stack-а, а Container — до максималне доступне величине унутар Stack-а.
IndexedStack је подкласа Stack-а која приказује само један елемент по наведеном индексу, али чува стање свих виџета у меморији. Ово је суштинска разлика у односу на пребацивање кроз условно приказивање (if-else или visibility), при чему се скривени виџети уништавају. Према Flutter Team (2025), IndexedStack се препоручује за BottomNavigationBar и TabBar, где треба сачувати стање сваког екрана.
IndexedStack(
index: 0,
children: [
HomeScreen(),
SearchScreen(),
ProfileScreen(),
],
)
При пребацивању index-а са 0 на 1 HomeScreen остаје у меморији и не губи своје стање (скроловање, унети подаци). IndexedStack користи механизам RepaintBoundary за изолацију прецртавања — само активни екран добија позив build. Ово смањује оптерећење GPU-а при пребацивању картица.
Размотримо три практична сценарија употребе Stack-а у реалним пројектима. Значка обавештења изнад иконе — класичан пример преклапања са Positioned. Опис са позиционирањем у односу на родитељски елемент. Cover слика са текстом изнад за картице чланака.
// Значка индикатор на иконици обавештења
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,
),
),
),
),
],
)
У овом примеру Positioned поставља црвени кружић-значку у горњем десном углу иконе обавештења. Параметри right: 0 и top: 0 причвршћују значку за границе Stack-а. Padding унутар Container-а ствара размак око текста како цифра не би приањала уз ивицу круга.
Често постављана питања
Stack приказује све елементе истовремено у виду слојева, а IndexedStack приказује само један по индексу. IndexedStack чува стање свих скривених елемената у меморији, што је згодно за BottomNavigationBar и TabBar. Према Flutter Docs (2025), IndexedStack користи исти механизам цртања као Stack, али примењује Offstage на неактивне елементе.
Користите својство alignment Stack-а, подешавањем Alignment.center. Ако текст треба да буде не-Positioned елемент, аутоматски ће се поравнати по центру Stack-а. Ако је текст унутар Positioned-а, поставите Positioned(left: 0, right: 0, top: 0, bottom: 0) и поравнање кроз својство textAlign у Text-у.
Stack и Overlay решавају различите задатке. Stack је виџет за распоред за изградњу структуре екрана са преклапањем слојева. Overlay је глобални слој изнад читаве хијерархије виџета за системске поруке (SnackBar, Tooltip). Према Flutter Team (2025), за обичне интерфејсе користите Stack, за привремена обавештења — Overlay.
Резиме
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође