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.
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()
}
}
- jetpack compose - TopAppBar center title
- jetpack compose - TopAppBar menu
- jetpack compose - Scaffold with Drawer
- jetpack compose - Open close drawer in code
- jetpack compose - How to use Button
- jetpack compose - How to use Card
- jetpack compose - How to use DropdownMenu
- jetpack compose - How to use Row layout
- jetpack compose - How to use Snackbar
- jetpack compose - CircularProgressIndicator example
- jetpack compose - RectangleShape example
- jetpack compose - Image from bitmap
- jetpack compose - Image shadow elevation
- jetpack compose - Image tint
- jetpack compose - How to use LazyRow