Scaffold — це composable-функція в Jetpack Compose, яка реалізує базову структуру екрану за специфікацією Material Design. Scaffold надає слоти для TopAppBar, BottomBar, FloatingActionButton, Drawer та Snackbar. За даними Google Android Documentation, 2025, Scaffold є обов'язковим елементом більшості екранів у застосунках на Compose, оскільки керує відступами для системних компонентів Material Design.
Головне
Scaffold — це composable-функція, яка реалізує каркас екрану відповідно до специфікації Material Design. Scaffold не є контейнером у звичному розумінні — це менеджер макету, який координує розташування кількох стандартних компонентів Material на екрані.
Scaffold керує відступами для TopAppBar, BottomBar та FloatingActionButton, а також системними елементами — статус-баром та навігаційною панеллю. Це гарантує, що контент не перекривається системними елементами та відповідає гайдлайнам Material Design.
За даними Material Design Guidelines, 2025, Scaffold має бути кореневим елементом кожного екрану застосунку. Він замінює застарілий CoordinatorLayout з View-системи та надає простіший і декларативніший API для побудови макету екрану.
Scaffold приймає параметри modifier, scaffoldState, topBar, bottomBar, floatingActionButton, drawerContent, snackbarHost та content. Параметр content отримує PaddingValues — відступи, які повинен враховувати основний контент.
@Composable
fun BasicScaffold() {
Scaffold(
topBar = {
TopAppBar(
title = { Text("Головна") }
)
},
floatingActionButton = {
FloatingActionButton(onClick = {}) {
Icon(Icons.Default.Add, contentDescription = "Add")
}
}
) { innerPadding ->
Column(
modifier = Modifier.padding(innerPadding)
) {
Text("Основний вміст")
}
}
}
topBar — слот для розміщення верхньої панелі застосунку, зазвичай TopAppBar або LargeTopAppBar. Scaffold автоматично додає відступ в innerPadding для контенту, щоб він не перекривався topBar. TopAppBar може містити заголовок, навігаційну іконку та дії.
bottomBar — слот для нижньої панелі навігації. Підтримує BottomNavigation, BottomAppBar або NavigationBar. Scaffold враховує висоту bottomBar при обчисленні innerPadding для контенту. За даними Material Design Guidelines, 2025, bottomBar слід використовувати на екранах з 3–5 точками навігації.
floatingActionButton — слот для плаваючої кнопки дії. Scaffold автоматично позиціонує FAB згідно зі специфікацією Material Design — у правому нижньому куті з коректним відступом. floatingActionButtonPosition дозволяє перемістити FAB у центр нижнього краю екрану.
У цьому прикладі Scaffold використовує всі основні слоти: TopAppBar із заголовком, BottomBar з трьома елементами навігації та FloatingActionButton для основної дії.
@Composable
fun FullScaffold() {
Scaffold(
topBar = {
TopAppBar(
title = { Text("Застосунок") },
navigationIcon = {
IconButton(onClick = {}) {
Icon(Icons.Default.Menu, "Menu")
}
}
)
},
bottomBar = {
NavigationBar {
NavigationBarItem(
icon = { Icon(Icons.Default.Home, "Головна") },
label = { Text("Home") },
selected = true,
onClick = {}
)
NavigationBarItem(
icon = { Icon(Icons.Default.Search, "Пошук") },
label = { Text("Search") },
selected = false,
onClick = {}
)
}
},
floatingActionButton = {
FloatingActionButton(onClick = {}) {
Icon(Icons.Default.Add, "Add")
}
}
) { innerPadding ->
Box(modifier = Modifier.padding(innerPadding)) {
Text("Вміст екрану")
}
}
}
ScaffoldState — об'єкт стану Scaffold, який об'єднує DrawerState та SnackbarHostState. DrawerState керує відкриттям та закриттям бокового меню, а SnackbarHostState — відображенням та приховуванням Snackbar. Стан створюється через rememberScaffoldState() та передається в параметр scaffoldState.
DrawerState надає методи open та close для програмного керування Drawer. Стан Drawer може бути відкритим, закритим або частково відкритим. drawerGesturesEnabled дозволяє вимкнути жест відкриття Drawer свайпом, залишивши лише програмне відкриття через кнопку.
SnackbarHostState керує Snackbar — тимчасовими сповіщеннями в нижній частині екрану. Метод showSnackbar відображає Snackbar з повідомленням та опціональною дією. За даними Material Design Guidelines, 2025, Snackbar слід використовувати для коротких повідомлень без критично важливої інформації.
@Composable
fun ScaffoldWithDrawer() {
val scaffoldState = rememberScaffoldState()
val scope = rememberCoroutineScope()
Scaffold(
scaffoldState = scaffoldState,
topBar = {
TopAppBar(
title = { Text("Меню") },
navigationIcon = {
IconButton(onClick = {
scope.launch {
scaffoldState.drawerState.open()
}
}) {
Icon(Icons.Default.Menu, "Menu")
}
}
)
},
drawerContent = {
Column(modifier = Modifier.padding(16.dp)) {
Text("Елемент 1")
Text("Елемент 2")
}
}
) { innerPadding ->
Box(modifier = Modifier.padding(innerPadding)) {
Text("Вміст")
}
}
}
Повний приклад екрану зі Scaffold включає TopAppBar, BottomNavigation, FloatingActionButton та Snackbar для відображення сповіщень при натисканні на FAB. ScaffoldState передається в усі компоненти для координації стану.
@Composable
fun MainScreen() {
val state = rememberScaffoldState()
val scope = rememberCoroutineScope()
Scaffold(
scaffoldState = state,
topBar = {
TopAppBar(
title = { Text("IT Sectr") },
actions = {
IconButton(onClick = {}) {
Icon(Icons.Default.Notifications, "Notifications")
}
}
)
},
bottomBar = {
NavigationBar {
NavigationBarItem(icon = { Icon(Icons.Default.Home, "Головна") },
label = { Text("Home") }, selected = true, onClick = {})
NavigationBarItem(icon = { Icon(Icons.Default.Settings, "Налаштування") },
label = { Text("Settings") }, selected = false, onClick = {})
}
},
floatingActionButton = {
FloatingActionButton(onClick = {
scope.launch {
state.snackbarHostState.showSnackbar("Готово")
}
}) {
Icon(Icons.Default.Add, "Add")
}
}
) { padding ->
Box(
modifier = Modifier.padding(padding).fillMaxSize(),
contentAlignment = Alignment.Center
) {
Text("Ласкаво просимо")
}
}
}
innerPadding — це PaddingValues, які Scaffold передає в content-блок. Вони містять відступи, необхідні для того, щоб контент не перекривався statusBar, navigationBar, topBar та bottomBar. Використання innerPadding обов'язкове для коректного відображення на різних пристроях.
Scaffold автоматично обчислює innerPadding на основі системних відступів та висоти встановлених слотів. На пристроях з камерою-острівцем або вирізом в екрані Scaffold коригує відступи для статус-бара. На старих пристроях з фізичними кнопками відступ знизу може бути відсутнім.
За даними Android Developers, 2024, innerPadding слід застосовувати до кореневого контейнера контенту через Modifier.padding(innerPadding). Якщо контент використовує scrollable container, innerPadding застосовується через Modifier.consumeWindowInsets для коректної роботи клавіатури та системних жестів.
Часті запитання
Scaffold — це не контейнер, а менеджер макету, який керує слотами для TopAppBar, BottomBar, FAB, Drawer та Snackbar, а також автоматично обробляє відступи для системних компонентів. Column та Box тільки розташовують елементи без урахування Material Design.
Scaffold рекомендується для екранів, що використовують компоненти Material Design. На простих екранах без TopAppBar, BottomBar або FAB Scaffold не обов'язковий, але він забезпечує коректні системні відступи через innerPadding, що корисно навіть без слотів.
Передайте ScaffoldState в параметр scaffoldState Scaffold, потім викличте state.snackbarHostState.showSnackbar(“Повідомлення”) всередині корутини. Scaffold автоматично відобразить Snackbar у нижній частині екрану.
Так, Scaffold створює внутрішній стан за замовчуванням, якщо scaffoldState не передано. Однак для керування Drawer та Snackbar програмно необхідно створити та передати ScaffoldState через rememberScaffoldState().
Використовуйте параметр floatingActionButtonPosition Scaffold. За замовчуванням FAB знаходиться праворуч унизу (FabPosition.End). Встановіть FabPosition.Center для розміщення FAB у центрі нижнього краю екрану.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також