Scaffold в Jetpack Compose — что это, свойства и как работает

Автор: IT Sectr Опубликовано: 2026-06-29 Время чтения: 11 мин

Scaffold — это composable-функция в Jetpack Compose, реализующая базовую структуру экрана по спецификации Material Design. Scaffold предоставляет слоты для TopAppBar, BottomBar, FloatingActionButton, Drawer и Snackbar. По данным Google Android Documentation, 2025, Scaffold является обязательным элементом большинства экранов в приложениях на Compose, так как управляет отступами для системных компонентов Material Design.

Главное

  • Scaffold — каркас экрана Material Design, который предоставляет слоты для TopAppBar, BottomBar, FAB, Drawer и Snackbar с корректными отступами.
  • ScaffoldState управляет состоянием Drawer и Snackbar, обеспечивая открытие и закрытие бокового меню и отображение уведомлений.
  • topBar, bottomBar и floatingActionButton — слоты Scaffold для интеграции стандартных компонентов Material Design.
  • drawerGesturesEnabled управляет жестом открытия бокового меню, а snackbarHost — кастомным отображением Snackbar.
  • Scaffold автоматически управляет отступами для статус-бара и навигационной панели через innerPadding.

Что такое Scaffold в Jetpack Compose

Scaffold — это composable-функция, реализующая каркас экрана в соответствии со спецификацией Material Design. Scaffold не является контейнером в привычном смысле — это менеджер макета, который координирует расположение нескольких стандартных компонентов Material на экране.

Scaffold управляет отступами для TopAppBar, BottomBar и FloatingActionButton, а также системными элементами — статус-баром и навигационной панелью. Это гарантирует, что контент не перекрывается системными элементами и соответствует гайдлайнам Material Design.

По данным Material Design Guidelines, 2025, Scaffold должен быть корневым элементом каждого экрана приложения. Он заменяет устаревший CoordinatorLayout из View-системы и предоставляет более простой и декларативный API для построения макета экрана.

Базовая сигнатура Scaffold

Scaffold принимает параметры modifier, scaffoldState, topBar, bottomBar, floatingActionButton, drawerContent, snackbarHost и content. Параметр content получает PaddingValues — отступы, которые должен учитывать основной контент.

kotlin
@Composable
fun BasicScaffold() {
    Scaffold(
        topBar = {
            TopAppBar(
                title = { Text("Home") }
            )
        },
        floatingActionButton = {
            FloatingActionButton(onClick = {}) {
                Icon(Icons.Default.Add, contentDescription = "Add")
            }
        }
    ) { innerPadding ->
        Column(
            modifier = Modifier.padding(innerPadding)
        ) {
            Text("Main content")
        }
    }
}

Слоты Scaffold: topBar, bottomBar и floatingActionButton

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 для основного действия.

kotlin
@Composable
fun FullScaffold() {
    Scaffold(
        topBar = {
            TopAppBar(
                title = { Text("App") },
                navigationIcon = {
                    IconButton(onClick = {}) {
                        Icon(Icons.Default.Menu, "Menu")
                    }
                }
            )
        },
        bottomBar = {
            NavigationBar {
                NavigationBarItem(
                    icon = { Icon(Icons.Default.Home, "Home") },
                    label = { Text("Home") },
                    selected = true,
                    onClick = {}
                )
                NavigationBarItem(
                    icon = { Icon(Icons.Default.Search, "Search") },
                    label = { Text("Search") },
                    selected = false,
                    onClick = {}
                )
            }
        },
        floatingActionButton = {
            FloatingActionButton(onClick = {}) {
                Icon(Icons.Default.Add, "Add")
            }
        }
    ) { innerPadding ->
        Box(modifier = Modifier.padding(innerPadding)) {
            Text("Screen content")
        }
    }
}

ScaffoldState: управление Drawer и Snackbar

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 должен использоваться для кратких сообщений без критически важной информации.

kotlin
@Composable
fun ScaffoldWithDrawer() {
    val scaffoldState = rememberScaffoldState()
    val scope = rememberCoroutineScope()

    Scaffold(
        scaffoldState = scaffoldState,
        topBar = {
            TopAppBar(
                title = { Text("Menu") },
                navigationIcon = {
                    IconButton(onClick = {
                        scope.launch {
                            scaffoldState.drawerState.open()
                        }
                    }) {
                        Icon(Icons.Default.Menu, "Menu")
                    }
                }
            )
        },
        drawerContent = {
            Column(modifier = Modifier.padding(16.dp)) {
                Text("Item 1")
                Text("Item 2")
            }
        }
    ) { innerPadding ->
        Box(modifier = Modifier.padding(innerPadding)) {
            Text("Content")
        }
    }
}

Пример построения экрана со Scaffold

Полный пример экрана со Scaffold включает TopAppBar, BottomNavigation, FloatingActionButton и Snackbar для отображения уведомлений при нажатии на FAB. ScaffoldState передаётся во все компоненты для координации состояния.

kotlin
@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, "Home") },
                    label = { Text("Home") }, selected = true, onClick = {})
                NavigationBarItem(icon = { Icon(Icons.Default.Settings, "Settings") },
                    label = { Text("Settings") }, selected = false, onClick = {})
            }
        },
        floatingActionButton = {
            FloatingActionButton(onClick = {
                scope.launch {
                    state.snackbarHostState.showSnackbar("Done")
                }
            }) {
                Icon(Icons.Default.Add, "Add")
            }
        }
    ) { padding ->
        Box(
            modifier = Modifier.padding(padding).fillMaxSize(),
            contentAlignment = Alignment.Center
        ) {
            Text("Welcome")
        }
    }
}

InnerPadding и адаптивная вёрстка со Scaffold

innerPadding — это PaddingValues, которые Scaffold передаёт в content-блок. Они содержат отступы, необходимые для того, чтобы контент не перекрывался statusBar, navigationBar, topBar и bottomBar. Использование innerPadding обязательно для корректного отображения на разных устройствах.

Scaffold автоматически вычисляет innerPadding на основе системных отступов и высоты установленных слотов. На устройствах с камерой-островком или вырезом в экране Scaffold корректирует отступы для статус-бара. На старых устройствах с физическими кнопками отступ снизу может отсутствовать.

По данным Android Developers, 2024, innerPadding должен применяться к корневому контейнеру контента через Modifier.padding(innerPadding). Если контент использует scrollable container, innerPadding применяется через Modifier.consumeWindowInsets для корректной работы клавиатуры и системных жестов.

  • Применяйте innerPadding к корневому контейнеру контента через Modifier.padding(innerPadding)
  • Для scrollable контейнеров используйте Modifier.consumeWindowInsets(innerPadding)
  • Не добавляйте дополнительные отступы для статус-бара — Scaffold делает это автоматически
  • При отсутствии topBar или bottomBar соответствующие отступы в innerPadding будут нулевыми

Часто задаваемые вопросы

Чем Scaffold отличается от обычного Column или Box?

Scaffold — это не контейнер, а менеджер макета, который управляет слотами для TopAppBar, BottomBar, FAB, Drawer и Snackbar, а также автоматически обрабатывает отступы для системных компонентов. Column и Box только располагают элементы без учёта Material Design.

Обязательно ли использовать Scaffold на каждом экране?

Scaffold рекомендуется для экранов, использующих компоненты Material Design. На простых экранах без TopAppBar, BottomBar или FAB Scaffold не обязателен, но он обеспечивает корректные системные отступы через innerPadding, что полезно даже без слотов.

Как показать Snackbar через Scaffold?

Передайте ScaffoldState в параметр scaffoldState Scaffold, затем вызовите state.snackbarHostState.showSnackbar("Сообщение") внутри корутины. Scaffold автоматически отобразит Snackbar в нижней части экрана.

Можно ли использовать Scaffold без scaffoldState?

Да, Scaffold создаёт внутреннее состояние по умолчанию, если scaffoldState не передан. Однако для управления Drawer и Snackbar программно необходимо создать и передать ScaffoldState через rememberScaffoldState().

Как изменить положение FloatingActionButton в Scaffold?

Используйте параметр floatingActionButtonPosition Scaffold. По умолчанию FAB находится справа внизу (FabPosition.End). Установите FabPosition.Center для размещения FAB в центре нижнего края экрана.

Итоги

  • Scaffold — каркас экрана Material Design с управлением слотами для TopAppBar, BottomBar, FAB, Drawer и Snackbar и автоматическими системными отступами.
  • topBar, bottomBar и floatingActionButton — слоты Scaffold для интеграции стандартных компонентов с корректным позиционированием.
  • ScaffoldState объединяет DrawerState и SnackbarHostState, обеспечивая программное управление боковым меню и уведомлениями через корутины.
  • innerPadding — обязательный параметр content-блока, содержащий отступы для системных элементов и установленных слотов Scaffold.
  • drawerGesturesEnabled и floatingActionButtonPosition — дополнительные параметры для тонкой настройки поведения Scaffold.
  • Scaffold автоматически обрабатывает отступы для статус-бара и навигационной панели на устройствах с разными конфигурациями экрана.
  • Для простых экранов без Material-компонентов Scaffold не обязателен, но рекомендуется как корневой элемент для корректной работы системных отступов.

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

IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

Читайте также