Scaffold provides a standard layout structure with slots for common UI elements like top bars, bottom bars, floating action buttons, and snackbars. It handles proper positioning and padding automatically.
Parameters
modifier
Modifier
default:"Modifier"
Modifier to be applied to the scaffold
topBar
@Composable () -> Unit
default:"{}"
Top app bar composable, typically a TopBar component
bottomBar
@Composable () -> Unit
default:"{}"
Bottom bar composable, typically a NavigationBar
snackbarHost
@Composable () -> Unit
default:"{}"
Snackbar host for displaying snackbars
floatingActionButton
@Composable () -> Unit
default:"{}"
Floating action button composable
floatingActionButtonPosition
FabPosition
default:"FabPosition.End"
Position of the FAB. Can be FabPosition.End or FabPosition.Center
containerColor
Color
default:"AppTheme.colors.background"
Background color of the scaffold
contentColor
Color
default:"contentColorFor(containerColor)"
Color for content inside the scaffold
contentWindowInsets
WindowInsets
default:"ScaffoldDefaults.contentWindowInsets"
Window insets to be applied to the content
content
@Composable (PaddingValues) -> Unit
required
Main content of the scaffold. Receives PaddingValues to account for top and bottom bars
Usage Examples
Basic Scaffold
Scaffold { paddingValues ->
Column(
modifier = Modifier
.padding(paddingValues)
.fillMaxSize()
) {
Text("Main content")
}
}
Scaffold with Top Bar
Scaffold(
topBar = {
TopBar {
Text("App Title")
}
}
) { paddingValues ->
// Content automatically padded to account for top bar
LazyColumn(
modifier = Modifier.padding(paddingValues)
) {
items(20) {
Text("Item $it")
}
}
}
Scaffold with Bottom Navigation
var selectedItem by remember { mutableStateOf(0) }
Scaffold(
bottomBar = {
NavigationBar {
NavigationBarItem(
selected = selectedItem == 0,
onClick = { selectedItem = 0 },
icon = { Icon(Icons.Default.Home, null) },
label = { Text("Home") }
)
NavigationBarItem(
selected = selectedItem == 1,
onClick = { selectedItem = 1 },
icon = { Icon(Icons.Default.Search, null) },
label = { Text("Search") )
)
}
}
) { paddingValues ->
Box(modifier = Modifier.padding(paddingValues)) {
// Content
}
}
Scaffold with FAB
Scaffold(
floatingActionButton = {
FloatingActionButton(
onClick = { /* Add action */ }
) {
Icon(Icons.Default.Add, contentDescription = "Add")
}
},
floatingActionButtonPosition = FabPosition.End
) { paddingValues ->
// Content
}
Complete Scaffold
val snackbarHostState = remember { SnackbarHostState() }
Scaffold(
topBar = {
TopBar {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
IconButton(onClick = { /* Menu */ }) {
Icon(Icons.Default.Menu, null)
}
Text("My App")
IconButton(onClick = { /* Settings */ }) {
Icon(Icons.Default.Settings, null)
}
}
}
},
bottomBar = {
NavigationBar {
// Navigation items
}
},
snackbarHost = {
SnackbarHost(snackbarHostState)
},
floatingActionButton = {
FloatingActionButton(onClick = { /* Action */ }) {
Icon(Icons.Default.Add, null)
}
}
) { paddingValues ->
LazyColumn(
modifier = Modifier
.padding(paddingValues)
.fillMaxSize()
) {
// List content
}
}
Scaffold with Custom Colors
Scaffold(
containerColor = Color(0xFF1E1E1E),
contentColor = Color.White,
topBar = { /* ... */ }
) { paddingValues ->
// Dark themed content
}
FAB Positioning
The FAB can be positioned in two ways:
// End position (default - bottom-right in LTR, bottom-left in RTL)
Scaffold(
floatingActionButtonPosition = FabPosition.End,
floatingActionButton = { /* FAB */ }
) { }
// Center position (bottom-center)
Scaffold(
floatingActionButtonPosition = FabPosition.Center,
floatingActionButton = { /* FAB */ }
) { }
Window Insets
Scaffold automatically handles system bars and window insets:
// Use default insets (system bars)
Scaffold(
contentWindowInsets = ScaffoldDefaults.contentWindowInsets
) { }
// Custom insets
Scaffold(
contentWindowInsets = WindowInsets(left = 16.dp, right = 16.dp)
) { }
// No insets
Scaffold(
contentWindowInsets = WindowInsets(0.dp)
) { }
Features
- Automatic Layout: Handles positioning of top bar, bottom bar, FAB, and snackbar
- Smart Padding: Content receives PaddingValues that account for bars
- Window Insets: Proper handling of system bars and notches
- Z-ordering: Correct layering of components (content, top bar, snackbar, bottom bar, FAB)
- RTL Support: Proper layout in right-to-left languages
- FAB Integration: FAB positioning accounts for bottom bar presence
Best Practices
- Always use the provided PaddingValues: Apply the padding from the content lambda to avoid content being hidden behind bars
Scaffold { paddingValues ->
LazyColumn(modifier = Modifier.padding(paddingValues)) {
// Content
}
}
-
Snackbar positioning: Snackbars automatically position themselves above the FAB or bottom bar
-
Top bar with scrolling: Combine with TopBar scroll behaviors for collapsing headers
Source Reference
Scaffold component implementation: components-lab/src/commonMain/kotlin/com/nomanr/lumo/ui/components/Scaffold.kt