Building a Bottom Sheet in Jetpack : A Step-by-Step Guide

This article demonstrates how to utilize Jetpack's rich libraries especially Jetpack Compose's ModalBottomSheet component to create a bottom sheet.

July 13, 20244 min read

Introduction

Developing user interfaces that improve user experience and interaction is a common step in the creation of modern Android applications. The bottom sheet is one such interface element that allows content to be displayed by sliding up from the bottom of the screen. This is a great method to present more options or information without having to navigate away from the current view. This tutorial will cover how to use Kotlin, a declarative UI framework that makes creating stunning, responsive interfaces more efficient and easy, to develop a bottom sheet in Jetpack Compose.

Compared to XML based Android UI development , Jetpack Compose makes it easier to create sophisticated UI components with fewer boilerplate code. You can create and manage UI elements more effectively by utilizing composables. Let us go over how to set up your project, create the main user interface (UI) with a button that opens the bottom sheet, and customize the content that appears on the bottom page in this article. This tutorial will provide you a thorough explanation of how to incorporate bottom sheets into your application, regardless of whether you want to add a straightforward menu, a form, or any other interactive features.We will use Jetpack Compose's ModalBottomSheet component to create a bottom sheet and Kotlin's coroutines for managing the sheet's state.

When providing contextual actions or additional content without diverting the user from their current job, a bottom sheet is especially helpful. By offering more options and maintaining the primary screen content visible, it improves the user experience. Jetpack Compose makes it easy to construct a bottom sheet, so you can concentrate on creating the interactions and content instead of worrying about the UI management details. You can easily develop dynamic and engaging user interfaces with Jetpack's robust toolbox and Kotlin's expressive syntax.

Step 1: Setup Your Project

Ensure you have Jetpack Compose dependencies in your build.gradle file:

Build.gradle

Image

plugins {
    alias(libs.plugins.android.application)
    alias(libs.plugins.jetbrains.kotlin.android)
}

android {
    namespace = "com.example.bottomsheets"
    compileSdk = 34

    defaultConfig {
        applicationId = "com.example.bottomsheets"
        minSdk = 24
        targetSdk = 34
        versionCode = 1
        versionName = "1.0"

        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
        vectorDrawables {
            useSupportLibrary = true
        }
    }

    buildTypes {
        release {
            isMinifyEnabled = false
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = "1.8"
    }
    buildFeatures {
        compose = true
    }
    composeOptions {
        kotlinCompilerExtensionVersion = "1.5.1"
    }
    packaging {
        resources {
            excludes += "/META-INF/{AL2.0,LGPL2.1}"
        }
    }
}

dependencies {

    implementation(libs.androidx.core.ktx)
    implementation(libs.androidx.lifecycle.runtime.ktx)
    implementation (libs.material3)
    implementation(libs.androidx.activity.compose)
    implementation(platform(libs.androidx.compose.bom))
    implementation(libs.androidx.ui)
    implementation(libs.androidx.ui.graphics)
    implementation(libs.androidx.ui.tooling.preview)
    implementation(libs.androidx.material3)
    testImplementation(libs.junit)
    androidTestImplementation(libs.androidx.junit)
    androidTestImplementation(libs.androidx.espresso.core)
    androidTestImplementation(platform(libs.androidx.compose.bom))
    androidTestImplementation(libs.androidx.ui.test.junit4)
    debugImplementation(libs.androidx.ui.tooling)
    debugImplementation(libs.androidx.ui.test.manifest)
}

Try Kodaschool for free

Click below to sign up and get access to free web, android and iOs challenges.

Sign Up

Step 2:Creating the Main Activity

Next, modify the MainActivity.kt file to remove the default Hello World logic.This activity will set the content to our MainScreen composable and act as the entry point for your application.

MainActivity.kt

Image

package com.example.bottomsheets
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.ui.Modifier
import com.example.bottomsheets.ui.theme.BottomSheetsTheme

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {
            BottomSheetsTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    MainScreen()
                }
            }
        }
    }
}

Step 3: Implementing the Main Screen

Now, create a new file named MainScreen.kt.The logic and button to display the bottom sheet will be included in this composable.

MainScreen.kt

Image

package com.example.bottomsheets
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import kotlinx.coroutines.launch
import androidx.compose.ui.unit.dp


@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MainScreen() {
    val sheetState = rememberModalBottomSheetState()
    val scope = rememberCoroutineScope()

    Scaffold(
        content = { contentPadding ->
            Column(
                modifier = Modifier
                    .fillMaxSize()
                    .padding(contentPadding),
                verticalArrangement = Arrangement.Center,
                horizontalAlignment = Alignment.CenterHorizontally
            ) {
                Button(onClick = {
                    scope.launch {
                        sheetState.show()
                    }
                }) {
                    Text("Show Bottom Sheet")
                }
            }

            if (sheetState.isVisible) {
                ModalBottomSheet(
                    onDismissRequest = {
                        scope.launch { sheetState.hide() }
                    },
                    sheetState = sheetState
                ) {
                    Column(
                        modifier = Modifier
                            .fillMaxSize()
                            .padding(16.dp)
                    ) {
                        CountryList()
                    }
                }
            }
        }
    )
}

Step 4:Creating the Country List

Finally, create a new file named Country.kt. This composable will contain a list of countries displayed in the bottom sheet.

Country.kt

Image
package com.example.bottomsheets
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp


@Composable
fun CountryList() {
    val countries = listOf(
        "Afghanistan", "Albania", "Algeria", "Andorra", "Angola", "Antigua and Barbuda", "Argentina",
        "Armenia", "Australia", "Austria", "Azerbaijan", "Bahamas", "Bahrain", "Bangladesh",
        "Barbados", "Belarus", "Belgium", "Belize", "Benin", "Bhutan", "Bolivia", "Bosnia and Herzegovina",
        "Botswana", "Brazil", "Brunei", "Bulgaria", "Burkina Faso", "Burundi", "Cabo Verde", "Cambodia",
        "Cameroon", "Canada", "Central African Republic", "Chad", "Chile", "China", "Colombia", "Comoros",
        "Congo", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic", "Denmark", "Djibouti",
        "Dominica", "Dominican Republic", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea",
        "Eritrea", "Estonia", "Eswatini", "Ethiopia", "Fiji", "Finland", "France", "Gabon", "Gambia",
        "Georgia", "Germany", "Ghana", "Greece", "Grenada", "Guatemala", "Guinea", "Guinea-Bissau",
        "Guyana", "Haiti", "Honduras", "Hungary", "Iceland", "India", "Indonesia", "Iran", "Iraq",
        "Ireland", "Israel", "Italy", "Jamaica", "Japan", "Jordan", "Kazakhstan", "Kenya", "Kiribati",
        "Kuwait", "Kyrgyzstan", "Laos", "Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein",
        "Lithuania", "Luxembourg", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta",
        "Marshall Islands", "Mauritania", "Mauritius", "Mexico", "Micronesia", "Moldova", "Monaco",
        "Mongolia", "Montenegro", "Morocco", "Mozambique", "Myanmar", "Namibia", "Nauru", "Nepal",
        "Netherlands", "New Zealand", "Nicaragua", "Niger", "Nigeria", "North Korea", "North Macedonia",
        "Norway", "Oman", "Pakistan", "Palau", "Palestine", "Panama", "Papua New Guinea", "Paraguay",
        "Peru", "Philippines", "Poland", "Portugal", "Qatar", "Romania", "Russia", "Rwanda", "Saint Kitts and Nevis",
        "Saint Lucia", "Saint Vincent and the Grenadines", "Samoa", "San Marino", "Sao Tome and Principe",
        "Saudi Arabia", "Senegal", "Serbia", "Seychelles", "Sierra Leone", "Singapore", "Slovakia", "Slovenia",
        "Solomon Islands", "Somalia", "South Africa", "South Korea", "South Sudan", "Spain", "Sri Lanka",
        "Sudan", "Suriname", "Sweden", "Switzerland", "Syria", "Taiwan", "Tajikistan", "Tanzania", "Thailand",
        "Timor-Leste", "Togo", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey", "Turkmenistan", "Tuvalu",
        "Uganda", "Ukraine", "United Arab Emirates", "United Kingdom", "United States", "Uruguay", "Uzbekistan",
        "Vanuatu", "Vatican City", "Venezuela", "Vietnam", "Yemen", "Zambia", "Zimbabwe"
    )

    Column(
        modifier = Modifier
            .fillMaxSize()
            .verticalScroll(rememberScrollState())
            .padding(16.dp),
        verticalArrangement = Arrangement.Top,
        horizontalAlignment = Alignment.Start
    ) {
        countries.forEach { country ->
            Text(text = country)
        }
    }
}

Step 5: Run App
When you run the app ,you will be able to see the Show Bottom Sheet Button that will launch the Bottom sheet when clicked.


ImageImage

Conclusion

In this tutorial,we have created a modal bottom sheet in a Jetpack Compose application by following the steps outlined in this article. Creating the main activity and screen, constructing a bottom sheet with a list of nations, and setting up the required dependencies have all been covered. These steps make it simple to add bottom sheets to your own Compose-based applications, giving users a cutting-edge and simple experience.

Learning how to use Jetpack Compose's components, such as the ModalBottomSheet, will enable you to construct Android UIs more declaratively and effectively. To build more intricate and captivating interfaces, you should practice further and try out various UI components.


Wilson Ochieng

About Wilson Ochieng

Android Expert developing mobile applications with 4+ Years of Experience.