Jetpack Compose: Scaffold Snackbar host

Introduction

In this example, we explore using the Scaffold component in Jetpack Compose to create a UI layout that incorporates a snackbar. A snackbar is a small, interactive notification bar that appears briefly at the bottom of the screen, providing user feedback and options like dismissing or interacting with the message. Jetpack Compose's Scaffold structure provides an efficient way to organize the UI elements of an Android application, including features like app bars, floating action buttons, and snackbars. This example demonstrates how to configure a Scaffold with a custom SnackbarHost that shows messages based on user interactions.

The goal of this example is to create a simple Android application using Jetpack Compose where users can trigger a snackbar by pressing a button. The snackbar displays dynamic messages and includes a "Hide" button that allows users to dismiss it. The example code is divided into two primary composable functions: GetScaffold and MainContent. Each function plays a crucial role in managing the UI structure and interaction flow.

Detailed Code Breakdown

The application starts with the MainActivity class, which extends AppCompatActivity. Inside the onCreate method, the setContent function is used to set up the UI layout. The setContent function is where Compose's declarative UI is initialized, specifying GetScaffold as the main composable function for the activity. This approach simplifies UI management by removing the need for XML layouts and allowing the entire UI to be managed within Kotlin code.

The GetScaffold composable function defines the primary structure of the UI using the Scaffold component. Here, we create a ScaffoldState object using rememberScaffoldState, which holds the state for the snackbar. Additionally, two MutableState objects, visibleState and snackBarMessage, are defined to manage the snackbar's visibility and message content. These state variables use the remember function to retain their values across recompositions, allowing the snackbar's visibility and text to persist while the UI updates.

Within the Scaffold, a TopAppBar component is configured as the app bar, which displays a simple title. The Scaffold also contains a snackbarHost, where the actual snackbar is defined. The snackbarHost only displays a snackbar if visibleState.value is set to true, ensuring that the snackbar only appears when it is triggered by the user. Inside the snackbar, a TextButton is provided with an action to hide the snackbar by setting visibleState.value to false. This snackbarHost feature allows for easy customization of the snackbar’s appearance and behavior.

The MainContent composable function contains the main interaction logic. This function is responsible for handling user actions and updating the snackbar's state. Inside MainContent, we define a counter variable, which tracks the number of times the snackbar is triggered. The counter is stored as a mutable state using the by keyword, making it reactive to UI changes. Additionally, a Box layout is used to center a button on the screen. The button’s onClick action uses a CoroutineScope to launch a coroutine that increments the counter, updates the visibleState to show the snackbar, and updates snackBarMessage to display the new counter value.

When the button is pressed, the snackbar displays a message indicating the number of times it has been triggered. For example, if the button is clicked three times, the snackbar message might read, "Hello, I am a snackbar (3)". This dynamic message feature demonstrates how to use MutableState objects to create interactive and responsive UI components in Jetpack Compose.

Summary

This example provides a clear illustration of how to use Jetpack Compose's Scaffold component to manage a snackbar notification. The GetScaffold function organizes the overall UI layout, while MainContent handles user interactions and snackbar visibility. By using rememberScaffoldState, MutableState, and coroutines, this example showcases how to manage state and create dynamic, responsive UI elements in an Android application.

Overall, this code serves as a helpful guide for building interactive UIs with Jetpack Compose, particularly for cases where user feedback through notifications is required. The approach demonstrates how to effectively integrate a Scaffold, snackbar, and state management to enhance the user experience in a clean and modern Android application.


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()
        )
        val visibleState:MutableState<Boolean> =
            remember { mutableStateOf(false) }
        val snackBarMessage:MutableState<String> =
            remember { mutableStateOf("This is a snackbar") }

        Scaffold(
            scaffoldState = scaffoldState,
            topBar = {
                TopAppBar(
                    title = { Text(
                        text = "Compose - Scaffold Snackbar host"
                    )},
                    backgroundColor = Color(0xFFC0E8D5),
                )
            },
            content = {MainContent(visibleState,snackBarMessage)},
            backgroundColor = Color(0xFFEDEAE0),
            snackbarHost = {
                if (visibleState.value){
                    Snackbar(
                        action = {
                            TextButton(
                                onClick = { visibleState.value = false }
                            ) {
                                Text(text = "Hide")
                            }
                        },
                        content = {
                            Text(text = snackBarMessage.value)
                        },
                        backgroundColor = Color(0xFFFF9966)
                    )
                }
            }
        )
    }


    @Composable
    fun MainContent(
        visibleState:MutableState<Boolean>,
        snackbarMessage:MutableState<String>
    ){
        val scope = rememberCoroutineScope()
        var counter by remember { mutableStateOf(0)}

        Box(
            modifier = Modifier.fillMaxSize(),
            contentAlignment = Alignment.Center
        ){
            Button(onClick = {
                scope.launch{
                    counter++
                    visibleState.value = true
                    snackbarMessage.value =
                        "Hello, i am a snackbar ($counter)"
                }
            }) {
                Text(text = "Show Snackbar")
            }
        }
    }
}
More android jetpack compose tutorials