Jetpack Compose: Scaffold with Snackbar

Introduction

In this article, we will explore how to implement a Scaffold layout in Android’s Jetpack Compose using Kotlin, specifically focusing on integrating a Snackbar for user notifications. Scaffold is a powerful composable in Jetpack Compose that allows developers to set up the fundamental structure of an app, including UI elements such as a TopAppBar, BottomAppBar, FloatingActionButton, Drawer, and Snackbar. Here, we will create a simple interface with a button that triggers a Snackbar to appear at the bottom of the screen. This example is suitable for developers looking to understand the basics of Scaffold and how to work with UI notifications in a modern, declarative style.

The project includes the MainActivity file, which serves as the main entry point for this Compose application. In this code, we define the structure with Scaffold, configure a TopAppBar for the app’s title, and create a centered button. This button, when clicked, triggers the display of a Snackbar, allowing users to experience a quick notification in response to their action. Let’s go through the code in a structured way to understand how each component works.

Code Breakdown: Setting Up the Main Activity

The MainActivity class extends AppCompatActivity and overrides the onCreate method, which is the main lifecycle method where we initialize our UI. Here, setContent is called, which sets the content view of this activity using a composable function. Instead of using an XML layout, we directly call the GetScaffold composable function, launching our custom UI in a fully Compose-based structure. This approach highlights Compose's declarative nature, as we define our UI through composable functions.

Creating the Scaffold Layout

The GetScaffold composable function is the heart of this setup. We first declare a scaffoldState, using the rememberScaffoldState function, to manage the state of the Scaffold and its SnackbarHost. This scaffoldState is necessary to handle the Snackbar’s behavior, ensuring we can control when and how it appears. Inside the Scaffold composable, we define the basic structure of our app. We include a TopAppBar component, which acts as the app’s title bar, setting its title to "Compose - Scaffold + Snackbar" and giving it a custom background color.

In addition to the TopAppBar, GetScaffold includes a content section that points to the MainContent composable function. The background color of the Scaffold itself is set to a light tone (Color(0xFFEDEAE0)), which helps visually separate the Scaffold from its inner content. This layout approach ensures that the Scaffold, including the Snackbar, can function independently within the larger UI.

Displaying the Snackbar with MainContent

The MainContent composable function houses the main interaction element—a button that triggers the Snackbar. To display the Snackbar on button click, we use a coroutine scope, created with rememberCoroutineScope(), to handle the asynchronous nature of the Snackbar's appearance. A Box composable is used to center the button within the available space. Modifier.fillMaxSize() ensures that the Box fills the screen, and contentAlignment = Alignment.Center aligns the button to the center of the Box, creating a visually balanced layout.

The button inside the Box has an onClick lambda that, when triggered, launches a coroutine using scope.launch. Inside this coroutine, we call scaffoldState.snackbarHostState.showSnackbar, passing in a message string—“I am a Snackbar”—which is displayed in the Snackbar. The coroutine scope and scaffoldState work together to handle the Snackbar’s lifecycle, ensuring it appears smoothly and disappears automatically after a short duration. This structure makes it easy to add more interactive elements or notifications in the future, leveraging the same Scaffold and SnackbarHost setup.

Previewing the Composable

Lastly, the ComposablePreview function is annotated with @Preview, which enables developers to preview the composable in the Android Studio design editor. Though this preview function is commented out (//GetScaffold()), it would normally display the layout without needing to run the app on a device or emulator. This feature is valuable during development, as it provides a real-time preview, allowing developers to adjust and fine-tune the layout directly in the IDE.

Summary

This example demonstrates how Jetpack Compose simplifies creating structured layouts with interactive elements like Snackbars. By leveraging the Scaffold composable, we can efficiently manage UI components such as TopAppBars and Snackbars within a single, cohesive layout. The coroutine scope allows us to manage Snackbar state asynchronously, making it a responsive and flexible UI element for notifying users of actions.

This approach showcases the power of Compose’s declarative style and Kotlin’s concise syntax, making it an excellent choice for modern Android development. With a well-organized scaffold, it’s easy to extend this setup with additional features like navigation or floating action buttons, offering a foundation for building complex, responsive UIs with minimal boilerplate.


MainActivity.kt

package com.cfsuman.jetpackcompose

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.material.Text
import androidx.compose.material.TopAppBar
import androidx.compose.material.icons.filled.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import kotlinx.coroutines.launch


class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            GetScaffold()
        }
    }


    @Composable
    fun GetScaffold(){
        val scaffoldState: ScaffoldState = rememberScaffoldState(
            snackbarHostState = SnackbarHostState()
        )

        Scaffold(
            scaffoldState = scaffoldState,
            topBar = {
                TopAppBar(
                    title = { Text(text = "Compose - Scaffold + Snackbar")},
                    backgroundColor = Color(0xFFC0E8D5),
                )
            },
            content = {MainContent(scaffoldState)},
            backgroundColor = Color(0xFFEDEAE0),
        )
    }


    @Composable
    fun MainContent(scaffoldState: ScaffoldState){
        val scope = rememberCoroutineScope()

        Box(
            modifier = Modifier.fillMaxSize(),
            contentAlignment = Alignment.Center
        ){
            Button(onClick = {
                scope.launch{
                    scaffoldState.snackbarHostState.showSnackbar(
                        message = "I am a Snackbar",
                    )
                }
            }) {
                Text(text = "Show Snackbar")
            }
        }
    }


    @Preview
    @Composable
    fun ComposablePreview(){
        //GetScaffold()
    }
}
More android jetpack compose tutorials