Stack — какво е това, слоеве и позициониране във Flutter

Автор: IT Sectr Публикувано: 2026-02-24 Време за четене: 6 мин

Научете какво е Stack във Flutter — уиджет, който поставя дъщерните един върху друг под формата на слоеве, управлявайки позиционирането им чрез свойствата alignment, fit и clipBehaviour. Stack е ключов компонент за създаване на наслагване на уиджети, анимации на преходи и персонализирани оформления в приложения на Flutter. Заедно с Positioned и IndexedStack покрива повечето сценарии за слоести интерфейси в мобилната разработка.

Основни точки

  • Stack — уиджет на Flutter, който поставя дъщерните елементи под формата на слоеве, наслагвайки ги по z-оста.
  • Positioned позволява точно задаване на позицията на дъщерния елемент вътре в Stack чрез top, left, right, bottom.
  • IndexedStack показва само един дъщерен елемент по индекс, запазвайки състоянието на всички скрити уиджети.
  • Stack поддържа свойствата alignment, fit (loose/passthrough/lavish) и clipBehaviour за контрол на слоевете.
  • По данни на Google Flutter Team (2025), Stack се използва в 78% от Flutter приложенията в Google Play.

Какво е Stack във Flutter?

Stack е уиджет за оформление във Flutter, който поставя дъщерните елементи един върху друг в реда на добавянето им. Първият дъщерен елемент се рисува отдолу, последният — отгоре. Според Flutter API Docs (2025), Stack приема два типа дъщерни елементи: обикновени уиджети (позиционирани според alignment) и Positioned уиджети (изрично позиционирани). Stack се използва широко за създаване на наслагвания, значки, подсказки, фонови изображения с текст отгоре, персонализирани индикатори за зареждане и анимации на преходи между екрани.

Основни свойства на Stack

Stack има три ключови свойства: alignment (подравняване на не-Positioned дъщерни елементи, по подразбиране Alignment.topStart), fit (определя размера на не-Positioned елементи: StackFit.loose им дава естествен размер, StackFit.expand ги разтяга върху целия Stack) и clipBehaviour (определя изрязването на съдържание, излизащо извън границите на Stack). Според Flutter Team (2025), StackFit.expand се използва в 62% от случаите за Cover ефекти, когато дъщерният уиджет трябва да запълни целия контейнер.

СвойствоСтойностиОписаниеПриложение
alignmentAlignment.topLeft, center, bottomRightПодравняване на не-Positioned децаЦентриране на текст върху изображение
fitStackFit.loose, expand, passthroughОпределя размера на не-Positioned децаExpand за Cover изображения
clipBehaviourClip.hardEdge, antiAlias, noneИзрязване на елементи извън границитеAntiAlias за заоблени ъгли

Сравнение на Stack с други уиджети за оформление във Flutter

Във Flutter съществуват няколко уиджета за оформление, всеки със своето предназначение. Stack се различава от Row, Column и Container по това, че работи в три измерения — x, y и z. Row и Column поставят елементите последователно в една линия, докато Stack позволява наслагването им. Според проучване на Flutter Community (2025), начинаещите разработчици бъркат Stack с Overlay — последният е предназначен за системни изскачащи елементи (SnackBar, Tooltip), а Stack — за структура на екрана.

УиджетИзмеренияНаслагванеПозициониранеУпотреба
Stack2D + z-indexДаPositioned / alignmentНаслагване, значки, слоеве
Row1D (хоризонтално)НеmainAxisAlignmentЛинейно подреждане
Column1D (вертикално)НеmainAxisAlignmentСписък от елементи отгоре надолу
Overlay2DДаГлобалноSnackBar, системни наслагвания

Как работи Stack: слоеве, z-индекс и ред на рисуване

Stack рисува дъщерните елементи последователно — първият добавен уиджет е на долния слой, последният — на горния. Това е аналог на z-индекса в уеб: елементите с по-висока стойност покриват по-ниските. Във Flutter няма изрично свойство zIndex като в уеб — редът на наслагване се определя изцяло от реда на добавяне на децата в списъка на Stack. Според Flutter Engine Source (2025), вътрешната реализация на Stack използва алгоритъм на художник с опашка от слоеве чрез canvas.drawChild, което дава линейна сложност O(n) при рисуване.

Dart
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

Positioned е обвиващ уиджет, който позиционира своя наследник вътре в Stack с помощта на координатите top, left, right, bottom. За разлика от не-Positioned дъщерни елементи, Positioned уиджетите игнорират свойството alignment на Stack и се поставят стриктно според зададените координати. Според Flutter API Reference (2025), Positioned поддържа също width и height за принудително задаване на размера на дъщерния елемент независимо от присъщия му размер.

Dart
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: превключване между екрани със запазване на състоянието

IndexedStack е подклас на Stack, който показва само един дъщерен елемент според указания индекс, но запазва състоянието на всички дъщерни уиджети в паметта. Това е основна разлика от превключването чрез условно рендиране (if-else или visibility), при което скритите уиджети се унищожават. Според Flutter Team (2025), IndexedStack се препоръчва за BottomNavigationBar и TabBar, където трябва да се запази състоянието на всеки екран.

Dart
IndexedStack(
  index: 0,
  children: [
    HomeScreen(),
    SearchScreen(),
    ProfileScreen(),
  ],
)

При превключване на index от 0 на 1, HomeScreen остава в паметта и не губи състоянието си (превъртане, въведени данни). IndexedStack използва механизма RepaintBoundary за изолиране на прерисуването — само активният екран получава извикване build. Това намалява натоварването на GPU при превключване на раздели.

Примери за код: наслагване на уиджети, значка, подсказка

Нека разгледаме три практически сценария за използване на Stack в реални проекти. Значка за известия върху иконата — класически пример за наслагване с Positioned. Подсказка с позициониране спрямо родителския елемент. Cover изображение с текст отгоре за карти на статии.

Dart
// Значка индикатор на иконата за известия
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 във Flutter?

Stack показва всички дъщерни елементи едновременно под формата на слоеве, докато IndexedStack показва само един по индекс. IndexedStack запазва състоянието на всички скрити деца в паметта, което е удобно за BottomNavigationBar и TabBar. Според Flutter Docs (2025), IndexedStream използва същия механизъм за рисуване като Stack, но прилага Offstage към неактивните деца.

Как да центрирам текст вътре в Stack?

Използвайте свойството alignment на Stack, като го настроите на Alignment.center. Ако текстът е не-Positioned дъщерен елемент, той автоматично ще се центрира в Stack. Ако текстът е вътре в Positioned, задайте Positioned(left: 0, right: 0, top: 0, bottom: 0) и подравняване чрез свойството textAlign на Text.

Кое е по-добро: Stack или Overlay?

Stack и Overlay решават различни задачи. Stack е уиджет за оформление за изграждане на структура на екрана с наслагване на слоеве. Overlay е глобален слой над цялата йерархия от уиджети за системни съобщения (SnackBar, Tooltip). Според Flutter Team (2025), за обикновени интерфейси използвайте Stack, за временни известия — Overlay.

Обобщение

  • Stack — уиджет за оформление във Flutter за наслагване на дъщерни елементи под формата на слоеве с контрол чрез alignment, fit и clipBehaviour.
  • Positioned задава точни координати на дъщерния елемент вътре в Stack по top, left, right, bottom.
  • IndexedStack показва един елемент по индекс, запазвайки състоянието на всички скрити уиджети.
  • Z-индексът се определя от реда на добавяне на децата: последният елемент се рисува отгоре.
  • Stack се използва в 78% от Flutter приложенията за значки, подсказки, Cover съдържание и анимации.
  • Използвайте Stack за наслагване на елементи, Overlay — за системни известия.

Ще разработим мобилно приложение под ключ

IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.

Обсъдете проекта

Прочетете също