Jetpack Compose: Snackbar action

Introduction

Jetpack Compose is a modern toolkit for building native Android UI, simplifying the process with a declarative approach. One of its handy UI components is the Snackbar, which provides lightweight feedback to users. This feedback often includes a message and an optional action, allowing users to take a specific step directly from the Snackbar. In this example, we’ll explore how to create a Snackbar in Android using Kotlin and Jetpack Compose, with an action to change the background color of the app. This setup allows for a dynamic, interactive UI that responds to user actions, showcasing how Jetpack Compose handles user feedback seamlessly.

In this tutorial, we’ll break down a Kotlin code example that creates a simple Android app with a button. When the button is clicked, a Snackbar appears at the bottom of the screen with an option to change the background color. We’ll explore how each function in the code contributes to building this UI, from setting up the Scaffold structure to handling coroutine-based Snackbar actions in Jetpack Compose.

Detailed Breakdown of Code

The entry point of this Android application is the MainActivity class. It extends AppCompatActivity and overrides the onCreate method, which is the typical lifecycle method where the main content view is set up. Here, instead of using traditional XML-based layouts, we use setContent to specify a composable function, GetScaffold, as the content. GetScaffold sets up a basic structure with a top bar and main content area, utilizing the Scaffold composable from Jetpack Compose. This Scaffold manages various elements of the UI, including the top app bar, background color, and Snackbar handling.

The GetScaffold function defines the UI's scaffold layout and initializes a ScaffoldState, which keeps track of the state of the Snackbar and other UI elements within the scaffold. We use rememberScaffoldState to remember the state across recompositions, ensuring that the Snackbar behaves consistently even when the UI is redrawn. Within the Scaffold, a TopAppBar is created at the top, displaying the title “Compose - Snackbar Action” with a light green background color. The content parameter of the Scaffold is set to the MainContent composable, which contains the button that triggers the Snackbar.

The MainContent composable is responsible for displaying the button in the center of the screen and handling the Snackbar action. Here, we use the Box layout to fill the available space (fillMaxSize()) and center-align the button within it. The background color of this box is managed by a mutable state variable bgColor, initialized to a pinkish color. The Button composable within the box contains an onClick listener, which launches a coroutine to show the Snackbar and handle the user’s response.

Inside the button's onClick lambda, a coroutine scope is used to launch a coroutine. The coroutine calls scaffoldState.snackbarHostState.showSnackbar to display the Snackbar. The showSnackbar method takes two main parameters: message and actionLabel. In this example, the message is set to “Change app background,” and the actionLabel is set to “Apply Green,” indicating the action the user can take. The SnackbarResult from showSnackbar returns a result based on the user’s action. If the user taps on the action button (“Apply Green”), the result will be SnackbarResult.ActionPerformed, and the code then changes the background color to green.

Summary

This example demonstrates the simplicity and power of Jetpack Compose for creating interactive UI elements in Android, such as Snackbar notifications with actions. Through this example, we saw how to use Scaffold, TopAppBar, SnackbarHostState, and coroutines to manage UI state and actions in a modern, declarative way. The Snackbar's action not only provides feedback but also allows the user to trigger changes in the UI, making it an effective tool for enhancing user experience.

Overall, Jetpack Compose's composable functions and state management make it easy to create dynamic, responsive UIs. This example offers a clear, concise way to add feedback mechanisms to an app, equipping developers with essential tools for building engaging Android applications.


MainActivity.kt

package com.cfsuman.jetpackcompose

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.activity.compose.setContent
import androidx.compose.foundation.background
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 Action")},
                    backgroundColor = Color(0xFFC0E8D5),
                )
            },
            content = {MainContent(scaffoldState)},
            backgroundColor = Color(0xFFEDEAE0),
        )
    }


    @Composable
    fun MainContent(scaffoldState: ScaffoldState){
        val scope = rememberCoroutineScope()
        var bgColor by remember { mutableStateOf(Color(0XFFF4C2C2))}

        Box(
            modifier = Modifier.fillMaxSize().background(bgColor),
            contentAlignment = Alignment.Center
        ){
            Button(onClick = {
                scope.launch{
                    val snackbarResult = scaffoldState
                        .snackbarHostState.showSnackbar(
                            message = "Change app background",
                            actionLabel = "Apply Green"
                        )

                    when(snackbarResult){
                        SnackbarResult.ActionPerformed -> {
                            bgColor = Color(0xFF7BB661)
                        }
                    }
                }
            }) {
                Text(text = "Show Snackbar")
            }
        }
    }
}
More android jetpack compose tutorials