DEV Community

myougaTheAxo
myougaTheAxo

Posted on

Scaffold Complete Guide — TopBar, BottomBar, FAB & Drawer Integration

Scaffold Complete Guide — TopBar, BottomBar, FAB & Drawer Integration

Master Jetpack Compose's Scaffold: the foundational component for Material Design 3 layouts. Learn TopAppBar integration, BottomNavigationBar patterns, Floating Action Buttons, and ModalNavigationDrawer combinations with production-ready code.

1. Basic Scaffold with TopAppBar

The simplest Scaffold pattern: TopAppBar with title, navigation icon, and action buttons.

@Composable
fun BasicScaffoldExample() {
    Scaffold(
        topBar = {
            TopAppBar(
                title = { Text("My App") },
                navigationIcon = {
                    IconButton(onClick = { /* navigate back */ }) {
                        Icon(Icons.Default.ArrowBack, contentDescription = "Back")
                    }
                },
                actions = {
                    IconButton(onClick = { /* search */ }) {
                        Icon(Icons.Default.Search, contentDescription = "Search")
                    }
                    IconButton(onClick = { /* menu */ }) {
                        Icon(Icons.Default.MoreVert, contentDescription = "More")
                    }
                }
            )
        },
        floatingActionButton = {
            FloatingActionButton(onClick = { /* add */ }) {
                Icon(Icons.Default.Add, contentDescription = "Add")
            }
        }
    ) { paddingValues ->
        LazyColumn(modifier = Modifier.padding(paddingValues)) {
            items(20) { index ->
                Text(
                    "Item $index",
                    modifier = Modifier.padding(16.dp)
                )
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Key points:

  • TopAppBar takes title, navigationIcon, actions
  • floatingActionButton parameter accepts single FAB
  • Content lambda receives PaddingValues — always apply to avoid overlap

2. BottomNavigationBar Integration

Add bottom navigation with multiple screens.

enum class BottomNavItem(val route: String, val icon: ImageVector, val label: String) {
    Home("home", Icons.Default.Home, "Home"),
    Search("search", Icons.Default.Search, "Search"),
    Profile("profile", Icons.Default.Person, "Profile")
}

@Composable
fun ScaffoldWithBottomNav() {
    var selectedItem by remember { mutableIntStateOf(0) }
    val items = BottomNavItem.entries

    Scaffold(
        topBar = {
            TopAppBar(title = { Text("MyApp") })
        },
        bottomBar = {
            NavigationBar {
                items.forEachIndexed { index, item ->
                    NavigationBarItem(
                        selected = selectedItem == index,
                        onClick = { selectedItem = index },
                        icon = { Icon(item.icon, contentDescription = item.label) },
                        label = { Text(item.label) }
                    )
                }
            }
        }
    ) { paddingValues ->
        Box(
            modifier = Modifier
                .fillMaxSize()
                .padding(paddingValues),
            contentAlignment = Alignment.Center
        ) {
            Text("${items[selectedItem].label} Screen")
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

3. Collapsing LargeTopAppBar with Scroll Behavior

Implement Material 3 collapsing header for expanded to small transitions.

@Composable
fun CollapsingTopAppBarExample() {
    val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()

    Scaffold(
        modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
        topBar = {
            LargeTopAppBar(
                title = {
                    Text(
                        "Large TopBar",
                        modifier = Modifier.padding(bottom = 16.dp)
                    )
                },
                scrollBehavior = scrollBehavior
            )
        }
    ) { paddingValues ->
        LazyColumn(modifier = Modifier.padding(paddingValues)) {
            items(50) { index ->
                Card(
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(8.dp)
                ) {
                    Text("Item $index", modifier = Modifier.padding(16.dp))
                }
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Note: nestedScroll() + scrollBehavior enables smooth collapse animation.

4. Detail Screen Pattern with Action Bar

Back button, share, and delete actions on detail view.

@Composable
fun DetailScreenScaffold(onBack: () -> Unit) {
    var showDeleteDialog by remember { mutableStateOf(false) }

    Scaffold(
        topBar = {
            TopAppBar(
                title = { Text("Item Details") },
                navigationIcon = {
                    IconButton(onClick = onBack) {
                        Icon(Icons.Default.ArrowBack, contentDescription = "Back")
                    }
                },
                actions = {
                    IconButton(onClick = { /* share */ }) {
                        Icon(Icons.Default.Share, contentDescription = "Share")
                    }
                    IconButton(onClick = { showDeleteDialog = true }) {
                        Icon(Icons.Default.Delete, contentDescription = "Delete")
                    }
                }
            )
        }
    ) { paddingValues ->
        Column(
            modifier = Modifier
                .padding(paddingValues)
                .padding(16.dp)
                .verticalScroll(rememberScrollState())
        ) {
            Text("Item Title", style = MaterialTheme.typography.headlineSmall)
            Spacer(modifier = Modifier.height(8.dp))
            Text("Detailed description here...", style = MaterialTheme.typography.bodyMedium)
        }
    }

    if (showDeleteDialog) {
        AlertDialog(
            onDismissRequest = { showDeleteDialog = false },
            title = { Text("Delete Item?") },
            confirmButton = {
                Button(onClick = { showDeleteDialog = false; onBack() }) {
                    Text("Delete")
                }
            },
            dismissButton = {
                Button(onClick = { showDeleteDialog = false }) {
                    Text("Cancel")
                }
            }
        )
    }
}
Enter fullscreen mode Exit fullscreen mode

5. ModalNavigationDrawer + Scaffold Combo

Side drawer with Scaffold for navigation.

@Composable
fun DrawerScaffoldExample() {
    val drawerState = rememberDrawerState(DrawerValue.Closed)
    val scope = rememberCoroutineScope()
    var selectedItem by remember { mutableIntStateOf(0) }

    ModalNavigationDrawer(
        drawerState = drawerState,
        drawerContent = {
            ModalDrawerSheet {
                Text("My App", modifier = Modifier.padding(16.dp), style = MaterialTheme.typography.headlineSmall)
                Divider()
                listOf("Home", "Settings", "About").forEachIndexed { index, label ->
                    NavigationDrawerItem(
                        label = { Text(label) },
                        selected = selectedItem == index,
                        onClick = {
                            selectedItem = index
                            scope.launch { drawerState.close() }
                        }
                    )
                }
            }
        }
    ) {
        Scaffold(
            topBar = {
                TopAppBar(
                    title = { Text("Main") },
                    navigationIcon = {
                        IconButton(
                            onClick = { scope.launch { drawerState.open() } }
                        ) {
                            Icon(Icons.Default.Menu, contentDescription = "Menu")
                        }
                    }
                )
            }
        ) { paddingValues ->
            Box(
                modifier = Modifier
                    .fillMaxSize()
                    .padding(paddingValues),
                contentAlignment = Alignment.Center
            ) {
                Text("Selected: ${listOf("Home", "Settings", "About")[selectedItem]}")
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Summary

Scaffold is the backbone of Material Design 3 layouts:

  • TopAppBar/CenterAlignedTopAppBar/LargeTopAppBar — title & actions
  • NavigationBar — bottom navigation
  • ModalNavigationDrawer — side navigation
  • FloatingActionButton — primary action
  • Always apply PaddingValues to content to avoid overlap

Use nestedScroll() + scrollBehavior for smooth collapse effects. Chain ModalNavigationDrawer → Scaffold for complex UIs.


8 Android app templates: Gumroad

Top comments (0)