Jetpack Compose: Snackbar host state

Introduction

In modern Android development, Jetpack Compose has become the preferred toolkit for building UI in a declarative style, allowing developers to quickly create responsive and flexible layouts. One of the components available in Jetpack Compose is the Snackbar, a lightweight feedback mechanism that can be used to inform users about actions or provide short messages. In this article, we will explore how to create a simple yet powerful Snackbar using the SnackbarHostState to manage multiple Snackbars and showcase them in a controlled, coroutine-friendly environment. This guide walks through the Kotlin code needed to create an app with a button that displays Snackbars sequentially when clicked.

This example code demonstrates how to build a scaffold layout using Jetpack Compose and configure a button to trigger multiple Snackbars through the SnackbarHostState. By following these steps, developers can gain an understanding of Compose's state handling, the coroutine scope, and how the Snackbar works within an Android application.

MainActivity Setup

The entry point for this app is the MainActivity class, which inherits from AppCompatActivity. In the onCreate method, we set up the content view with the setContent function, a Compose-specific method for defining UI. Here, setContent initializes the GetScaffold composable function as the main content of the activity. This approach allows the entire UI to be built using Compose components and eliminates the need for XML-based layouts.

Defining the GetScaffold Composable

The GetScaffold composable is responsible for creating the Scaffold layout, which serves as a structural component for the screen. It defines a TopAppBar and provides a layout framework that can include floating action buttons, bottom navigation bars, and more. In this case, Scaffold includes a top app bar with a title, "Compose - Snackbar host state." The color of the top bar is set to a custom light green using hexadecimal values, enhancing the app's aesthetic while maintaining code readability.

Inside GetScaffold, we declare a scaffoldState using rememberScaffoldState, which initializes the SnackbarHostState to manage Snackbar messages. This state is essential because it lets the app store and control the visibility of Snackbars. Finally, the main content of the screen is provided by the MainContent composable, with scaffoldState passed as an argument for Snackbar management.

Implementing the MainContent Composable

In MainContent, we define a centered button within a Box layout that fills the available space on the screen. This layout choice allows the button to be prominently positioned, making it easy for users to trigger the Snackbar series. The MainContent function also initializes a coroutine scope with rememberCoroutineScope, which is essential for asynchronous operations in Compose. The coroutine scope lets us handle Snackbar display timing without blocking the main thread, creating a smooth user experience.

When the button is clicked, a coroutine is launched to display ten consecutive Snackbars using a repeat loop. The showSnackbar method within scaffoldState.snackbarHostState is invoked for each Snackbar, with the message containing a number to indicate the order. The Snackbar duration is set to SnackbarDuration.Short, meaning each Snackbar will briefly appear before the next one is shown. This coroutine-based approach makes it easy to manage the sequential display of Snackbars without complex state handling or callback-based mechanisms.

Summary

This Kotlin example illustrates the power of Jetpack Compose's declarative style in managing UI elements like Snackbars. By using SnackbarHostState and coroutines, we create an elegant solution for displaying a series of Snackbars with minimal code. The Scaffold structure organizes our layout, while the coroutine scope allows asynchronous, non-blocking interactions, ensuring a responsive user experience.

With this approach, Android developers can easily incorporate Snackbars into their Compose projects, taking advantage of state management and composable layouts to create clean, efficient code. This example offers a solid foundation for integrating Snackbars in more complex applications, providing users with a clear, contextual way to receive feedback on their actions.


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.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 - Snackbar host state"
                    )},
                    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{
                    repeat(10){index->
                        scaffoldState
                            .snackbarHostState.showSnackbar(
                                message = "This is a Snackbar (${index+1})",
                                duration = SnackbarDuration.Short
                            )
                    }
                }
            }) {
                Text(text = "Show Snackbars")
            }
        }
    }
}
More android jetpack compose tutorials