Jetpack Compose: How to use ModalDrawer

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.


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.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()
    }
}
More android jetpack compose tutorials