Introduction
In this article, we'll explore how to use the ModalDrawer
component in Jetpack Compose, a popular UI toolkit for Android development. Jetpack Compose simplifies building Android UIs by offering a declarative approach, allowing developers to describe how the UI should look based on the app’s data state. The ModalDrawer
component is particularly useful for creating a sliding drawer that appears over the main content, often containing navigation or additional options. This layout element can improve app usability, providing a familiar navigation structure in Android apps.
The example code we'll discuss showcases how to create a ModalDrawer
in an Android application using Kotlin and Jetpack Compose. We’ll break down each part, from setting up the activity to customizing the drawer’s appearance and functionality. By the end, you’ll understand how to implement and control a ModalDrawer
in your app, as well as how to handle opening and closing interactions with coroutines.
Setting Up MainActivity
The code begins by setting up MainActivity
, which extends AppCompatActivity
. The onCreate
method initializes the UI using setContent { GetScaffold() }
, where GetScaffold
is a custom composable function that organizes the main structure of the screen. Using setContent
in Jetpack Compose applications is essential, as it binds the Compose-based UI with the traditional Android activity lifecycle.
In this setup, GetScaffold
is called to display a layout scaffold, providing a structured screen layout that includes a top app bar, main content, and background color. This composable is structured to make the ModalDrawer
easily accessible as part of the primary content of the activity.
GetScaffold Composable Function
The GetScaffold
composable function defines the layout structure with the Scaffold
composable, which is commonly used to implement the basic material design structure, including elements like the top app bar and bottom navigation. Here, the Scaffold
includes a TopAppBar
component for the title and main content, which is provided by the MainContent
composable. The top bar is customized with a title that reads "Compose - How To Use ModalDrawer" in white text, set against a dark background color (hex code #3D0C02
), giving it a distinctive look.
The main background color of the Scaffold
is set to a soft beige color (hex code #EDEAE0
). This setup makes the drawer and the main content stand out against the background, enhancing the user experience by providing visual clarity and separation between different screen components.
Creating the ModalDrawer with MainContent
The MainContent
composable function houses the ModalDrawer
, providing the primary interactive drawer functionality. It begins by creating a DrawerState
variable using rememberDrawerState(DrawerValue.Closed)
, which maintains the drawer’s open or closed state. rememberDrawerState
enables state management within the composable, allowing the drawer to respond dynamically to user interactions.
A coroutine scope, scope
, is also initialized using rememberCoroutineScope()
. This coroutine scope is necessary to manage the asynchronous opening and closing of the drawer in response to button clicks. With Jetpack Compose, coroutines are essential for managing state changes that should happen in the background without blocking the main UI thread.
Defining ModalDrawer Properties
Within the ModalDrawer
, various properties are defined to customize its look and feel. The drawerShape
is set to MaterialTheme.shapes.small
, giving the drawer a predefined shape according to material design principles. Colors for the drawer background, content, and scrim are customized to match the app’s overall theme, using shades of pink (#F19CBB
), dark brown (#1B1811
), and light yellow (#FAE7B5
). This careful use of color helps establish a visually cohesive experience for users.
Additional properties like drawerElevation
and gesturesEnabled
add to the drawer’s usability and aesthetics. Setting the drawerElevation
to 12 dp gives it a slight shadow effect, adding depth and making the drawer appear to float over the main content. The gesturesEnabled
property allows users to swipe open and close the drawer, providing a natural interaction that aligns with standard Android behavior.
Drawer Content and Main Content Layout
The drawer’s content is defined within a Box
composable, containing a Text
element that reads "Go To Home." This box takes up the full width of the drawer and is padded to ensure the text is visually separated from the drawer’s edges. The text style is set to MaterialTheme.typography.h6
, giving it prominence and making it suitable for navigation or title-like content within the drawer.
The main content outside the drawer consists of a Column
layout, centered both horizontally and vertically. This column contains a single Button
composable, allowing users to control the drawer’s state. The button text dynamically changes based on whether the drawer is open or closed, using an inline if
statement to display either "Open Drawer" or "Close Drawer." When the button is clicked, a coroutine launches, toggling the drawer state between open and closed, ensuring smooth transitions.
Composable Preview Function
Finally, there’s a ComposablePreview
function annotated with @Preview
, a useful feature in Jetpack Compose for testing and visualizing the UI within the Android Studio editor. Though it’s commented out in this example, calling GetScaffold()
here would allow developers to preview the entire UI layout, including the drawer, without needing to run the app on an emulator or physical device.
Summary
This example demonstrates how to implement a ModalDrawer
in an Android app using Jetpack Compose, highlighting key concepts such as state management, coroutine-based interactivity, and layout customization. By using Jetpack Compose, developers can create complex UI structures like modal drawers more efficiently and with greater flexibility compared to traditional XML-based layouts.
Through this example, you now have a solid understanding of how to integrate a ModalDrawer
into your app, including customizing its appearance and managing its state with Jetpack Compose’s composable functions and coroutine support. This approach not only enhances your app’s navigation experience but also aligns with modern Android development practices.
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.foundation.shape.CutCornerShape
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.material.Text
import androidx.compose.material.TopAppBar
import androidx.compose.material.rememberDrawerState
import androidx.compose.ui.Alignment
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.draw.clip
import kotlinx.coroutines.launch
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
GetScaffold()
}
}
@Composable
fun GetScaffold(){
Scaffold(
topBar = {TopAppBar(
title = {Text(
"Compose - How To Use ModalDrawer",
color = Color.White)},
backgroundColor = Color(0xFF3D0C02)) },
content = {MainContent()},
backgroundColor = Color(0xFFEDEAE0)
)
}
@Composable
fun MainContent(){
val drawerState = rememberDrawerState(DrawerValue.Closed)
val scope = rememberCoroutineScope()
ModalDrawer(
drawerState = drawerState,
drawerShape = MaterialTheme.shapes.small,
drawerBackgroundColor = Color(0xFFF19CBB),
drawerContentColor = Color(0XFF1B1811),
scrimColor = Color(0xFFFAE7B5),
drawerElevation = 12.dp,
gesturesEnabled = true,
modifier = Modifier.clip(
CutCornerShape(topEnd = 48.dp)
),
drawerContent = {
Box(
Modifier
.fillMaxWidth()
.padding(12.dp)) {
Text(
"Go To Home",
style = MaterialTheme.typography.h6
)
}
},
content = {
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Button(
onClick = { scope.launch{drawerState.open()}}
) {
Text(text = if(drawerState.isClosed)
"Open Drawer" else "Close Drawer")
}
}
}
)
}
@Preview
@Composable
fun ComposablePreview(){
//GetScaffold()
}
}
- jetpack compose - Row gravity
- jetpack compose - Row background
- jetpack compose - Column align bottom
- jetpack compose - Box center alignment
- jetpack compose - Box gradient background color
- jetpack compose - Box gravity
- jetpack compose - Card center
- jetpack compose - Card corner radius
- jetpack compose - Card padding
- jetpack compose - Card background color
- jetpack compose - Card alignment
- jetpack compose - How to use BadgeBox
- jetpack compose - Update state of another function variable
- jetpack compose - TopAppBar navigation
- jetpack compose - TopAppBar actions