Scaffold — це центральний віджет-каркас у Flutter, який реалізує базову структуру Material Design екрану з AppBar, Drawer, BottomNavigationBar та FloatingActionButton. Він не просто позиціонує елементи, а надає готову архітектуру з правильним z-порядком та обробкою користувацьких жестів. Згідно з документацією Flutter (2026), Scaffold є обов'язковим кореневим елементом для коректної роботи Material-компонентів, включаючи SnackBar та BottomSheet. На відміну від Container або Column, Scaffold автоматично керує SafeArea, адаптивним фоном та поведінкою клавіатури, що робить його стандартом для побудови екранів у мобільних застосунках.
Головне
Scaffold — це віджет-компонувальник з бібліотеки Material Design, який формує базову візуальну структуру екрану. Він реалізує стандартний патерн застосунку Material: верхня панель, тіло екрану, бічне меню та плаваючі кнопки. На відміну від Container, який просто задає розміри та стиль, Scaffold керує цілим екраном як єдиною системою.
Кожен Flutter-застосунок, побудований за Material Design, починається з MaterialApp, всередині якого кожен екран обгортається в Scaffold. Саме Scaffold забезпечує коректне відображення AppBar на всіх пристроях, враховуючи SafeArea для iPhone X та вище. Він також відповідає за z-порядок: Drawer відображається поверх body, а SnackBar — поверх усього інтерфейсу, але нижче діалогових вікон.
Згідно з офіційною довідкою Flutter API (2026), Scaffold є обов'язковою умовою для коректної роботи таких віджетів, як SnackBar, BottomSheet та PersistentBottomSheet. Без Scaffold ці компоненти викидають виняток, оскільки вони залежать від InheritedWidget Scaffold.of для доступу до контексту Scaffold. Тому розміщення будь-якого вмісту безпосередньо в Container замість Scaffold — поширена помилка початківців, яка призводить до втрати Material-функціональності.
У типовому Flutter-застосунку Scaffold знаходиться всередині MaterialApp, зазвичай під WidgetsApp або CupertinoApp при кросплатформенній розробці. MaterialApp створює Navigator та тему, а Scaffold визначає структуру поточного екрану. Кожен екран може мати власний Scaffold з унікальними AppBar, Drawer та BottomNavigationBar, що дозволяє гнучко налаштовувати інтерфейс під конкретну сторінку.
Для глибокої кастомізації Scaffold можна комбінувати з NestedScrollView — це дозволяє реалізувати складні скрол-ефекти, наприклад, зникаючий AppBar з parallax-ефектом. Однак у більшості випадків стандартного Scaffold з його властивостями достатньо для побудови production-ready екрану.
Scaffold складається з кількох обов'язкових та опціональних зон, кожна з яких відповідає за певну частину інтерфейсу. Розглянемо кожну частину окремо, щоб зрозуміти, як вони взаємодіють одна з одною.
AppBar — це верхня панель екрану, яка відображає заголовок, кнопку навігації та дії. Вона автоматично отримує правильну висоту 56dp та враховує SafeArea для пристроїв з «чолочною». В AppBar можна вбудувати TabBar для перемикання вкладок, використовуючи властивість bottom.
Drawer — це панель, що виїжджає зліва та надає навігацію по розділах застосунку. Scaffold автоматично додає іконку «гамбургер» в AppBar, якщо властивість drawer встановлена. Drawer може містити DrawerHeader, ListView з пунктами меню та користувацьку інформацію.
BottomNavigationBar — це панель у нижній частині екрану для перемикання між основними розділами. Вона містить від 2 до 5 іконок з підписами та підтримує Material 3 з активною індикацією через NavigationBar. Scaffold позиціонує її внизу екрану, автоматично зсуваючи body вище, щоб вміст не перекривався.
FloatingActionButton — це кругла кнопка, розміщена в правому нижньому куті екрану. Вона використовується для основної дії на екрані, наприклад, додавання нового запису або надсилання повідомлення. Scaffold підтримує кілька FAB з розширеною анімацією через extended властивості.
Body — це центральна область екрану, в яку поміщається основний вміст. Як body може виступати будь-який віджет: Column, ListView, GridView, Stack або кастомна композиція. Scaffold автоматично розраховує висоту body з урахуванням AppBar, BottomNavigationBar та SafeArea, що позбавляє від ручного підганяння розмірів.
Scaffold надає понад 30 властивостей для налаштування зовнішнього вигляду та поведінки екрану. Серед них є як обов'язкові (body), так і опціональні, що керують відступами, фоном та станом клавіатури. Розуміння кожної властивості допомагає точно налаштувати інтерфейс під вимоги дизайну.
| Властивість | Тип | Опис |
|---|---|---|
| appBar | PreferredSizeWidget? | Верхня панель екрану з заголовком та діями |
| body | Widget? | Основний вміст екрану між AppBar та BottomNavigationBar |
| drawer | Widget? | Бічна панель, що відкривається свайпом зліва |
| bottomNavigationBar | Widget? | Нижня панель навігації (BottomNavigationBar або NavigationBar) |
| floatingActionButton | Widget? | Плаваюча кнопка основної дії |
| backgroundColor | Color? | Колір фону Scaffold, що перевизначає тему |
| resizeToAvoidBottomInset | bool | Автоматичне стискання body при появі клавіатури |
Властивість resizeToAvoidBottomInset особливо важлива при роботі з формами: коли вона встановлена в true (за замовчуванням), Scaffold автоматично стискає body при появі клавіатури, щоб поле введення залишалося видимим. Це позбавляє від необхідності писати кастомні слухачі клавіатури. Для кастомних сценаріїв з SingleChildScrollView властивість можна вимкнути.
Розглянемо практичний приклад Scaffold з повним набором Material-компонентів. Код створює екран з AppBar, Drawer, BottomNavigationBar, FloatingActionButton та SnackBar — типова структура мобільного застосунку на Flutter.
class MainScreen extends StatefulWidget {
const MainScreen({super.key});
@override
State<MainScreen> createState() => _MainScreenState();
}
class _MainScreenState extends State<MainScreen> {
int selectedIndex = 0;
final List<Widget> pages = [
const HomePage(),
const SearchPage(),
const ProfilePage(),
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Мій застосунок'),
actions: [
IconButton(icon: const Icon(Icons.search), onPressed: () {}),
],
),
body: pages[selectedIndex],
drawer: Drawer(
child: ListView(
children: [
const DrawerHeader(child: Text('Меню')),
ListTile(title: const Text('Налаштування'), onTap: () {}),
],
),
),
bottomNavigationBar: NavigationBar(
selectedIndex: selectedIndex,
onDestinationSelected: (int index) {
setState(() => selectedIndex = index);
},
destinations: const [
NavigationDestination(icon: Icon(Icons.home), label: 'Home'),
NavigationDestination(icon: Icon(Icons.search), label: 'Search'),
NavigationDestination(icon: Icon(Icons.person), label: 'Profile'),
],
),
floatingActionButton: FloatingActionButton(
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Дію виконано')),
);
},
child: const Icon(Icons.add),
),
);
}
}
У прикладі використовується NavigationBar з Material 3 замість застарілого BottomNavigationBar. Scaffold автоматично пов'язує всі частини: при відкритті Drawer SnackBar приховується, при перемиканні вкладок body оновлюється, а FloatingActionButton залишається на місці. ScaffoldMessenger гарантує показ SnackBar навіть за наявності кількох Scaffold в ієрархії.
Material 3 (M3) — це еволюція Material Design, представлена Google у 2023 році. Scaffold у M3 отримав ряд змін: новий віджет NavigationBar замість BottomNavigationBar, підтримку Dynamic Color через ColorScheme.fromSeed та оновлені рекомендації щодо відступів та висоти компонентів. Перехід на M3 не вимагає заміни Scaffold — достатньо оновити тему застосунку.
Для включення Material 3 у проекті необхідно встановити useMaterial3: true в ThemeData. Scaffold автоматично адаптує візуальне оформлення: відступи стають більшими (24dp замість 16dp), кольори перераховуються з seed-кольору, а FloatingActionButton отримує більші розміри з закругленими кутами. При цьому всі існуючі властивості Scaffold залишаються робочими.
Згідно з специфікацією Material Design 3 (2026), рекомендується використовувати NavigationBar з трьома-п'ятьма пунктами замість BottomNavigationBar. Scaffold підтримує обидва варіанти, але NavigationBar забезпечує кращу підтримку адаптивності та Material You на пристроях Pixel.
Для коректної роботи Scaffold з M3 достатньо оновити тему та замінити BottomNavigationBar на NavigationBar. Кольори будуть автоматично розраховані через ColorScheme.fromSeed, а Scaffold підлаштує відступи під нові стандарти. При необхідності можна перевизначити backgroundColor безпосередньо.
Часті запитання
Scaffold — це віджет-каркас цілого екрану з підтримкою Material-компонентів (AppBar, Drawer, SnackBar), тоді як Container — це базовий контейнер для одного дочірнього елемента без керування структурою екрану. Scaffold надає z-порядок, SafeArea та автоматичну обробку жестів, а Container тільки задає розміри та стиль.
Технічно так, але на практиці це не рекомендується. Якщо вкласти один Scaffold в інший, внутрішній Scaffold створить власний AppBar та BottomNavigationBar, що призведе до дублювання панелей та плутанини в z-порядку. Для складних макетів використовуйте NestedScrollView або Column всередині body одного Scaffold.
SnackBar є дочірнім компонентом Scaffold і вимагає його присутності в дереві віджетів для коректного відображення. Scaffold надає ScaffoldState, через який SnackBar анімує появу та позиціонується в нижній частині екрану. Без Scaffold SnackBar викидає виняток, оскільки не може знайти ScaffoldState в контексті через InheritedWidget.
Колір фону Scaffold задається через властивість backgroundColor, яка перевизначає колір теми для конкретного екрану. Якщо потрібно змінити фон глобально, встановіть scaffoldBackgroundColor в ThemeData. Material 3 автоматично розраховує фоновий колір з ColorScheme.surface, але його можна перевизначити вручну.
ScaffoldMessenger — це утиліта, представлена у Flutter 2.5, яка дозволяє показувати SnackBar та BottomSheet незалежно від поточного Scaffold в ієрархії. На відміну від застарілого Scaffold.of(context), ScaffoldMessenger працює коректно при навігації між екранами і не втрачає контекст під час анімацій. Рекомендується завжди використовувати ScaffoldMessenger для зворотного зв'язку.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також