Scaffold — to funkcja composable w Jetpack Compose, implementująca podstawową strukturę ekranu zgodnie ze specyfikacją Material Design. Scaffold udostępnia sloty dla TopAppBar, BottomBar, FloatingActionButton, Drawer i Snackbar. Według Google Android Documentation, 2025, Scaffold jest obowiązkowym elementem większości ekranów w aplikacjach na Compose, ponieważ zarządza odstępami dla systemowych komponentów Material Design.
Najważniejsze
Scaffold — to funkcja composable, implementująca szkielet ekranu zgodnie ze specyfikacją Material Design. Scaffold nie jest kontenerem w tradycyjnym sensie — to menedżer układu, który koordynuje rozmieszczenie kilku standardowych komponentów Material na ekranie.
Scaffold zarządza odstępami dla TopAppBar, BottomBar i FloatingActionButton, a także elementami systemowymi — paskiem statusu i panelem nawigacyjnym. Gwarantuje to, że treść nie zachodzi na elementy systemowe i jest zgodna z wytycznymi Material Design.
Według Material Design Guidelines, 2025, Scaffold powinien być głównym elementem każdego ekranu aplikacji. Zastępuje on przestarzały CoordinatorLayout z systemu View i zapewnia prostsze i bardziej deklaratywne API do budowania układu ekranu.
Scaffold przyjmuje parametry modifier, scaffoldState, topBar, bottomBar, floatingActionButton, drawerContent, snackbarHost i content. Parametr content otrzymuje PaddingValues — odstępy, które musi uwzględnić główna treść.
@Composable
fun BasicScaffold() {
Scaffold(
topBar = {
TopAppBar(
title = { Text("Strona główna") }
)
},
floatingActionButton = {
FloatingActionButton(onClick = {}) {
Icon(Icons.Default.Add, contentDescription = "Add")
}
}
) { innerPadding ->
Column(
modifier = Modifier.padding(innerPadding)
) {
Text("Główna treść")
}
}
}
topBar — slot do umieszczenia górnego panelu aplikacji, zwykle TopAppBar lub LargeTopAppBar. Scaffold automatycznie dodaje odstęp w innerPadding dla treści, aby nie nachodziła na topBar. TopAppBar może zawierać tytuł, ikonę nawigacji i akcje.
bottomBar — slot dla dolnego panelu nawigacji. Obsługuje BottomNavigation, BottomAppBar lub NavigationBar. Scaffold uwzględnia wysokość bottomBar przy obliczaniu innerPadding dla treści. Według Material Design Guidelines, 2025, bottomBar powinien być używany na ekranach z 3–5 punktami nawigacji.
floatingActionButton — slot dla pływającego przycisku akcji. Scaffold automatycznie pozycjonuje FAB zgodnie ze specyfikacją Material Design — w prawym dolnym rogu z prawidłowym odstępem. floatingActionButtonPosition pozwala przenieść FAB na środek dolnej krawędzi ekranu.
W tym przykładzie Scaffold używa wszystkich głównych slotów: TopAppBar z tytułem, BottomBar z trzema elementami nawigacji i FloatingActionButton dla głównej akcji.
@Composable
fun FullScaffold() {
Scaffold(
topBar = {
TopAppBar(
title = { Text("Aplikacja") },
navigationIcon = {
IconButton(onClick = {}) {
Icon(Icons.Default.Menu, "Menu")
}
}
)
},
bottomBar = {
NavigationBar {
NavigationBarItem(
icon = { Icon(Icons.Default.Home, "Strona główna") },
label = { Text("Home") },
selected = true,
onClick = {}
)
NavigationBarItem(
icon = { Icon(Icons.Default.Search, "Szukaj") },
label = { Text("Search") },
selected = false,
onClick = {}
)
}
},
floatingActionButton = {
FloatingActionButton(onClick = {}) {
Icon(Icons.Default.Add, "Add")
}
}
) { innerPadding ->
Box(modifier = Modifier.padding(innerPadding)) {
Text("Treść ekranu")
}
}
}
ScaffoldState — obiekt stanu Scaffold, który łączy DrawerState i SnackbarHostState. DrawerState zarządza otwieraniem i zamykaniem menu bocznego, a SnackbarHostState — wyświetlaniem i ukrywaniem Snackbar. Stan tworzony jest przez rememberScaffoldState() i przekazywany do parametru scaffoldState.
DrawerState udostępnia metody open i close do programowego zarządzania Drawer. Stan Drawer może być otwarty, zamknięty lub częściowo otwarty. drawerGesturesEnabled pozwala wyłączyć gest otwierania Drawer przeciągnięciem, pozostawiając tylko programowe otwieranie przez przycisk.
SnackbarHostState zarządza Snackbar — tymczasowymi powiadomieniami w dolnej części ekranu. Metoda showSnackbar wyświetla Snackbar z wiadomością i opcjonalną akcją. Według Material Design Guidelines, 2025, Snackbar powinien być używany do krótkich komunikatów bez krytycznie ważnych informacji.
@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("Element 1")
Text("Element 2")
}
}
) { innerPadding ->
Box(modifier = Modifier.padding(innerPadding)) {
Text("Treść")
}
}
}
Pełny przykład ekranu ze Scaffold obejmuje TopAppBar, BottomNavigation, FloatingActionButton i Snackbar do wyświetlania powiadomień po naciśnięciu FAB. ScaffoldState jest przekazywany do wszystkich komponentów w celu koordynacji stanu.
@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, "Strona główna") },
label = { Text("Home") }, selected = true, onClick = {})
NavigationBarItem(icon = { Icon(Icons.Default.Settings, "Ustawienia") },
label = { Text("Settings") }, selected = false, onClick = {})
}
},
floatingActionButton = {
FloatingActionButton(onClick = {
scope.launch {
state.snackbarHostState.showSnackbar("Gotowe")
}
}) {
Icon(Icons.Default.Add, "Add")
}
}
) { padding ->
Box(
modifier = Modifier.padding(padding).fillMaxSize(),
contentAlignment = Alignment.Center
) {
Text("Witaj")
}
}
}
innerPadding — to PaddingValues, które Scaffold przekazuje do bloku content. Zawierają one odstępy niezbędne do tego, aby treść nie nachodziła na statusBar, navigationBar, topBar i bottomBar. Użycie innerPadding jest obowiązkowe dla prawidłowego wyświetlania na różnych urządzeniach.
Scaffold automatycznie oblicza innerPadding na podstawie odstępów systemowych i wysokości zainstalowanych slotów. Na urządzeniach z wyspą kamerki lub wycięciem w ekranie Scaffold koryguje odstępy dla paska statusu. Na starszych urządzeniach z fizycznymi przyciskami dolny odstęp może być zerowy.
Według Android Developers, 2024, innerPadding powinien być stosowany do głównego kontenera treści przez Modifier.padding(innerPadding). Jeśli treść używa kontenera przewijanego, innerPadding stosuje się przez Modifier.consumeWindowInsets do prawidłowej pracy klawiatury i gestów systemowych.
Często zadawane pytania
Scaffold — to nie kontener, a menedżer układu, który zarządza slotami dla TopAppBar, BottomBar, FAB, Drawer i Snackbar, a także automatycznie przetwarza odstępy dla komponentów systemowych. Column i Box tylko rozmieszczają elementy bez uwzględniania Material Design.
Scaffold jest zalecany dla ekranów korzystających z komponentów Material Design. Na prostych ekranach bez TopAppBar, BottomBar lub FAB Scaffold nie jest obowiązkowy, ale zapewnia prawidłowe systemowe odstępy przez innerPadding, co jest przydatne nawet bez slotów.
Przekaż ScaffoldState do parametru scaffoldState Scaffold, a następnie wywołaj state.snackbarHostState.showSnackbar(„Wiadomość”) wewnątrz korutyny. Scaffold automatycznie wyświetli Snackbar w dolnej części ekranu.
Tak, Scaffold tworzy wewnętrzny stan domyślnie, jeśli scaffoldState nie został przekazany. Jednak do programowego zarządzania Drawer i Snackbar należy utworzyć i przekazać ScaffoldState przez rememberScaffoldState().
Użyj parametru floatingActionButtonPosition Scaffold. Domyślnie FAB znajduje się po prawej stronie na dole (FabPosition.End). Ustaw FabPosition.Center, aby umieścić FAB na środku dolnej krawędzi ekranu.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również