Introduction
Jetpack Compose is Google's modern toolkit for building native Android UIs with declarative components. Among its many components, BackdropScaffold
provides an elegant way to display content in two distinct layers: a front layer and a back layer. This UI pattern allows users to switch between the layers to access different content areas while maintaining a smooth, fluid experience. In this article, we will explore a practical implementation of BackdropScaffold
in an Android app built with Kotlin and Jetpack Compose. The provided code demonstrates how to structure an app using this component, making the UI interactive and visually appealing.
In this example, we will break down the main components, including the creation of a backdrop scaffold, customizing the front and back layers, and managing the UI state with Compose. By the end of this article, you will understand how to set up a backdrop scaffold, control layer behavior, and handle user interactions effectively in your Compose application.
MainActivity: Setting the Content
The MainActivity
class, as usual in Android apps, serves as the entry point. In this case, the app’s UI is entirely built using Jetpack Compose. When the activity is created, setContent
is called, which sets the composable function GetScaffold
as the content of the activity. This composable will define the main structure of the backdrop scaffold, including the app bar and both the front and back layers.
Inside GetScaffold
, the BackdropScaffold
component is initialized. The BackdropScaffold
takes several parameters, including the app bar, back layer content, and front layer content. This method serves as the central structure of the UI, ensuring that the layout is dynamic and responsive.
Defining the BackdropScaffold State
The composable GetScaffold
function starts by defining a scaffold state using rememberBackdropScaffoldState
. This state controls the visibility of the back layer and manages transitions between the front and back layers. The initialValue
of the scaffold is set to BackdropValue.Concealed
, meaning the back layer starts hidden, with only the front layer visible.
Additionally, a MutableState
object is used to hold the currently selected icon, which dynamically updates as users interact with the buttons on the back layer. Initially, this state is set to Icons.Filled.Favorite
, and this value will change based on the user's selection.
AppBar and Layer Structure
The BackdropScaffold
composable includes an app bar, which is defined using the TopAppBar
composable. This app bar displays the title "Compose - Backdrop Scaffold" and features a background color of light blue. The app bar provides the familiar structure to the top of the app, giving it a professional look.
Next, the BackdropScaffold
specifies both the backLayerContent
and frontLayerContent
. The back layer contains a set of interactive buttons, while the front layer displays content based on the user's selection from the back layer. These two layers form the foundation of this UI pattern.
Back Layer Content: User Interaction
The BackLayerContent
composable defines the layout and behavior of the back layer. It consists of a column of buttons, each representing a different icon (Favorite, Email, and Phone). The content is centered inside a Box
that fills the screen and is given a blue background.
Each button is created using the OutlinedButton
composable. When clicked, the button changes the icon shown in the front layer and triggers a coroutine to hide (conceal) the back layer by calling backdropScaffoldState.conceal()
. This interaction between the user and the UI is powered by Jetpack Compose’s state management system, making the buttons responsive and dynamic.
Front Layer Content: Dynamic Display
The FrontLayerContent
composable handles the front layer's display. It uses the selectedIcon
state to show the icon chosen by the user from the back layer. The content is also centered within a Box
, which has a different blue shade for its background to distinguish it from the back layer.
This composable consists of an Icon
and a Text
element. The icon’s size is set to 250 dp, making it large and easily visible to the user, and it is tinted in a dark blue color. Below the icon, a simple text label ("Front layer content") is displayed. The dynamic relationship between the back and front layers enhances the interactivity and visual feedback of the UI.
Summary
The example code demonstrates the use of BackdropScaffold
in Jetpack Compose to create a dynamic, two-layer UI with a clear separation of front and back layer content. The front layer is designed to change based on user input from the back layer, providing a responsive experience that is easy to implement with Compose's state handling.
By combining essential Compose elements such as Box
, Column
, Icon
, and Text
, and utilizing state management with remember
and MutableState
, this code offers a clean, structured approach to creating modern Android UIs. The use of BackdropScaffold
is particularly useful for apps that need to present a secondary set of actions or options while keeping the primary content visible to users.
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.Icons
import androidx.compose.material.icons.filled.Email
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.Phone
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.launch
class MainActivity : AppCompatActivity() {
override fun onCreate(savedObjectState: Bundle?) {
super.onCreate(savedObjectState)
setContent {
GetScaffold()
}
}
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun GetScaffold(){
val backdropScaffoldState = rememberBackdropScaffoldState(
initialValue = BackdropValue.Concealed)
val selectedIcon = remember {
mutableStateOf(Icons.Filled.Favorite)}
BackdropScaffold(
scaffoldState = backdropScaffoldState,
appBar = {
TopAppBar(
title = { Text(
text = "Compose - Backdrop Scaffold"
)},
backgroundColor = Color(0xFF1ca9c9),
)
},
backLayerContent = {BackLayerContent(
backdropScaffoldState, selectedIcon
)},
frontLayerContent = { FrontLayerContent(
backdropScaffoldState, selectedIcon) },
)
}
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun BackLayerContent(
backdropScaffoldState: BackdropScaffoldState,
selectedIcon: MutableState<ImageVector>
){
val scope = rememberCoroutineScope()
Box(
modifier = Modifier.background(Color(0xFF5D8AA8))
.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Column(
verticalArrangement = Arrangement.spacedBy(12.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
OutlinedButton(onClick = {
selectedIcon.value = Icons.Filled.Favorite
scope.launch {
backdropScaffoldState.conceal()
}
}) {
Icon(Icons.Filled.Favorite, "")
Text(text = "Favorite")
}
OutlinedButton(onClick = {
selectedIcon.value = Icons.Filled.Email
scope.launch {
backdropScaffoldState.conceal()
}
}) {
Icon(Icons.Filled.Email, "")
Text(text = "Email")
}
OutlinedButton(onClick = {
selectedIcon.value = Icons.Filled.Phone
scope.launch {
backdropScaffoldState.conceal()
}
}) {
Icon(Icons.Filled.Phone, "")
Text(text = "Phone")
}
}
}
}
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun FrontLayerContent(
backdropScaffoldState: BackdropScaffoldState,
selectedIcon: MutableState<ImageVector>
){
Box(
modifier = Modifier.background(Color(0xFF89CFF0))
.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
Icon(
selectedIcon.value,
contentDescription = "",
Modifier.size(250.dp),
tint = Color(0xFF002147)
)
Text(text = "Front layer content")
}
}
}
}
- jetpack compose - Card padding
- jetpack compose - How to use ModalDrawer
- jetpack compose - TopAppBar actions
- jetpack compose - TopAppBar center title
- jetpack compose - Scaffold with Snackbar
- jetpack compose - Snackbar action
- jetpack compose - Scaffold Snackbar host
- jetpack compose - How to use AndroidView
- jetpack compose - How to use bottom navigation
- jetpack compose - How to use navigation controller
- jetpack compose - Navigation object argument
- jetpack compose - Room add remove update
- jetpack compose - How to use WebView
- jetpack compose - WebView ProgressIndicator
- jetpack compose - WebView progress percentage