Open In App

Scaffold in Android using Jetpack Compose

Improve
Improve
Like Article
Like
Save
Share
Report

There are a lot of apps that contain TopAppBar, Drawer, Floating Action Button, BottomAppBar (in the form of bottom navigation), Snackbar. While you can individually set up all of these in an app but takes a lot of setups. Jetpack Compose provides Scaffold Composable which can save a lot of time. It’s like a prebuilt template. In this article, we will see how to set up Scaffold in android with Jetpack Compose. We will be building a basic app that will demonstrate the Scaffold composable, here is a video showing the app.

Prerequisites:

Step by Step Implementation

Step 1: Creating TopAppBar

Open MainActivity.kt and create a TopBar Composable function, It will be a wrapper for our TopAppBar in Scaffold.

Kotlin




// A function which will receive a 
// callback to trigger to opening the drawer
@Composable
fun TopBar(onMenuClicked: () -> Unit) {
  
    // TopAppBar Composable
    TopAppBar(
        // Provide Title
        title = {
            Text(text = "Scaffold||GFG", color = Color.White)
        },
        // Provide the navigation Icon (Icon on the left to toggle drawer)
        navigationIcon = {
            Icon(
                imageVector = Icons.Default.Menu,
                contentDescription = "Menu",
                  
                // When clicked trigger onClick 
                // Callback to trigger drawer open
                modifier = Modifier.clickable(onClick = onMenuClicked), 
                tint = Color.White
            )
        },
        // background color of topAppBar
        backgroundColor = Color(0xFF0F9D58)
    )
}


Step 2: Create BottomAppBar

Open MainActivity.kt and create a BottomBar Composable. It will be a simple straight forward in our app.

Kotlin




@Composable
fun BottomBar() {
    // BottomAppBar Composable
    BottomAppBar(
        backgroundColor = Color(0xFF0F9D58)
    ) {
        Text(text = "Bottom App Bar", color = Color.White)
    }
}


Step 3: Create Drawer content

Open MainActivity.kt and create a composable Drawer, It will be the drawer in our Scaffold.

Kotlin




@Composable
fun Drawer() {
    // Column Composable
    Column(
        Modifier
            .background(Color.White)
            .fillMaxSize()
    ) {
        // Repeat is a loop which
        // takes count as argument 
        repeat(5) { item ->
            Text(text = "Item number $item", modifier = Modifier.padding(8.dp), color = Color.Black)
        }
    }
}


Step 4: Creating Body part of Scaffold

Create another composable function Body. It will be a simple Text composable in our app. Be sure to customize it when implementing it in other apps.

Kotlin




@Composable
fun Body() {
    Column(
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally,
        modifier = Modifier
            .fillMaxSize()
            .background(Color.White)
    ) {
        Text(text = "Body Content", color = Color(0xFF0F9D58))
    }
}


Since all the components we need are done, let’s work on the Scaffold Part.

Step 5: Working with Scaffold

Since we have already created all the components, the Scaffold code will be pretty simple and self-explanatory.

Kotlin




@Composable
fun ScaffoldExample() {
  
    // create a scaffold state, set it to close by default
    val scaffoldState = rememberScaffoldState(rememberDrawerState(DrawerValue.Closed))
  
    // Create a coroutine scope. Opening of 
    // Drawer and snackbar should happen in
    // background thread without blocking main thread
    val coroutineScope = rememberCoroutineScope()
  
    // Scaffold Composable
    Scaffold(
        
        // pass the scaffold state
        scaffoldState = scaffoldState,
        
        // pass the topbar we created
        topBar = {
            TopBar(
                // When menu is clicked open the
                // drawer in coroutine scope
                onMenuClicked = {
                    coroutineScope.launch {
                        // to close use -> scaffoldState.drawerState.close()
                        scaffoldState.drawerState.open()
                    }
                })
        },
        
        // pass the bottomBar
        // we created
        bottomBar = { BottomBar() },
        
        // Pass the body in
        // content parameter
        content = {
            Body()
        },
        
        // pass the drawer
        drawerContent = {
            Drawer()
        },
  
        floatingActionButton = {
            // Create a floating action button in 
            // floatingActionButton parameter of scaffold
            FloatingActionButton(
  
                onClick = {
                    // When clicked open Snackbar
                    coroutineScope.launch {
                        when (scaffoldState.snackbarHostState.showSnackbar(
                            // Message In the snackbar
                            message = "Snack Bar"
                            actionLabel = "Dismiss"
                        )) {
                            SnackbarResult.Dismissed -> {
                                // do something when 
                               // snack bar is dismissed
                            }
  
                            SnackbarResult.ActionPerformed -> {
                            // when it appears
                            }
                        }
                    }
                }) {
                // Simple Text inside FAB
                Text(text = "X")
            }
        }
    )
}


Now call this composable from setContent in Mainactivity class

Kotlin




class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent { 
            Surface(color = Color.White) {
                // Scaffold we created
                ScaffoldExample()
            }         
        }
    }
}


Now run the app and see it working.

Complete code:

Kotlin




package com.gfg.scaffoldjetpackcompose
  
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Menu
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.launch
  
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            Surface(color = Color.White) {
                // Scaffold we created
                ScaffoldExample()
            }
        }
    }
}
  
@Composable
fun ScaffoldExample() {
  
    // create a scaffold state, set it to close by default
    val scaffoldState = rememberScaffoldState(rememberDrawerState(DrawerValue.Closed))
  
    // Create a coroutine scope. Opening of Drawer
    // and snackbar should happen in background 
    // thread without blocking main thread
    val coroutineScope = rememberCoroutineScope()
  
    // Scaffold Composable
    Scaffold(
        
        // pass the scaffold state
        scaffoldState = scaffoldState,
        
        // pass the topbar we created
        topBar = {
            TopBar(
                // When menu is clicked open the
                // drawer in coroutine scope
                onMenuClicked = {
                    coroutineScope.launch {
                        // to close use -> scaffoldState.drawerState.close()
                        scaffoldState.drawerState.open()
                    }
                })
        },
        
        // pass the bottomBar we created
        bottomBar = { BottomBar() },
        
        // Pass the body in
        // content parameter
        content = {
            Body()
        },
        
        // pass the drawer
        drawerContent = {
            Drawer()
        },
  
        floatingActionButton = {
            // Create a floating action button in
            // floatingActionButton parameter of scaffold
            FloatingActionButton(
                onClick = {
                    // When clicked open Snackbar
                    coroutineScope.launch {
                        when (scaffoldState.snackbarHostState.showSnackbar(
                            // Message In the snackbar
                            message = "Snack Bar"
                            actionLabel = "Dismiss"
                        )) {
                            SnackbarResult.Dismissed -> {
                                // do something when 
                                // snack bar is dismissed
                            }
  
                            SnackbarResult.ActionPerformed -> {
                            // when it appears
                            }
  
                        }
                    }
                }) {
                // Simple Text inside FAB
                Text(text = "X")
            }
        }
    )
}
  
// A function which will receive a 
// callback to trigger to opening the drawer
@Composable
fun TopBar(onMenuClicked: () -> Unit) {
    // TopAppBar Composable
    TopAppBar(
        // Provide Title
        title = {
            Text(text = "Scaffold||GFG", color = Color.White)
        },
        // Provide the navigation Icon ( Icon on the left to toggle drawer)
        navigationIcon = {
            Icon(
                imageVector = Icons.Default.Menu,
                contentDescription = "Menu",
  
                   // When clicked trigger onClick 
                  // Callback to trigger drawer open
                modifier = Modifier.clickable(onClick = onMenuClicked),
                tint = Color.White
            )
        },
        // background color of topAppBar
        backgroundColor = Color(0xFF0F9D58)
    )
}
  
@Composable
fun BottomBar() {
    // BottomAppBar Composable
    BottomAppBar(
        backgroundColor = Color(0xFF0F9D58)
    ) {
        Text(text = "Bottom App Bar", color = Color.White)
    }
}
  
@Composable
fun Body() {
    Column(
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally,
        modifier = Modifier
            .fillMaxSize()
            .background(Color.White)
    ) {
        Text(text = "Body Content", color = Color(0xFF0F9D58))
    }
}
  
  
@Composable
fun Drawer() {
    // Column Composable
    Column(
        Modifier
            .background(Color.White)
            .fillMaxSize()
    ) {
        // Repeat is a loop which
        // takes count as argument
        repeat(5) { item ->
            Text(text = "Item number $item", modifier = Modifier.padding(8.dp), color = Color.Black)
        }
    }
}


Output:

Get the complete project from GitHub.



Last Updated : 28 Jul, 2021
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads