Android Jetpack

Create a Dropdown Menu in Jetpack Compose

Pinterest LinkedIn Tumblr

In this post, we will learn to add a dropdown menu to your Jetpack Compose. Developers called it different names also that are Popup menu, context menu, and drop-down menu. As far as the name is not important, concepts are important. So In this tutorial, we’ll walk you through the steps to create a dropdown menu in your Jetpack Compose app, so you can provide your users with a seamless and intuitive experience. Let’s get started!

Understand the basics of Compose UI

Before we dive into creating a dropdown menu in Jetpack Compose, it’s important to have a basic understanding of what Jetpack Compose is and how it works.

Jetpack Compose is a modern toolkit for building native Android UIs using Kotlin. It allows developers to create UI components using a declarative syntax, which makes it easier to build and maintain complex UIs.

Below UI I will use in this demo

drop down menu examples

Create DropDownItem data class

data class DropDownItem(
    val text: String
)

Create a list of items for the dropdown menu

The first step in creating a dropdown menu in Jetpack Compose is to create a list of items that will be displayed in the menu. This can be done using a simple list of strings or a more complex data structure, depending on your needs.

For example, if you’re creating a dropdown menu for a person list. Once you have your list of items, you can move on to creating the dropdown menu itself.

@Composable
fun PersonItem(
  personName: String,
  dropdownItems: List<DropDownItem>,
  modifier: Modifier = Modifier,
  onItemClick: (DropDownItem) -> Unit
) 

Use the DropdownMenu component to create the menu

The DropdownMenu component is a built-in component in Jetpack Compose that allows you to create a dropdown menu with ease. To use it, you’ll need to pass in the list of items you created earlier, as well as a selected item and a callback function to handle changes to the selected item.

You can customize the appearance of the menu using various properties, such as the width and height, the background color, and the text color. With just a few lines of code, you can have a fully functional dropdown menu in your Jetpack Compose app.

package com.dropdownmenucompose

import androidx.compose.foundation.LocalIndication
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.indication
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.PressInteraction
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Person
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Modifier
import androidx.compose.runtime.*
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.DpOffset
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp

data class DropDownItem(
  val text: String
)

@Composable
fun PersonItem(
  personName: String,
  dropdownItems: List<DropDownItem>,
  modifier: Modifier = Modifier,
  onItemClick: (DropDownItem) -> Unit
) {
  var isContextMenuVisible by rememberSaveable {
    mutableStateOf(false)
  }
  var pressOffset by remember {
    mutableStateOf(DpOffset.Zero)
  }
  var itemHeight by remember {
    mutableStateOf(0.dp)
  }
  val interactionSource = remember {
    MutableInteractionSource()
  }
  val density = LocalDensity.current

  Card(elevation = 4.dp, modifier = modifier.onSizeChanged {
    itemHeight = with(density) { it.height.toDp() }
  }) {
    Box(modifier = Modifier
      .fillMaxWidth()
      .indication(interactionSource, LocalIndication.current)
      .pointerInput(true) {
        detectTapGestures(onLongPress = {
          isContextMenuVisible = true
          pressOffset = DpOffset(it.x.toDp(), it.y.toDp())
        }, onPress = {
          val press = PressInteraction.Press(it)
          interactionSource.emit(press)
          tryAwaitRelease()
          interactionSource.emit(PressInteraction.Release(press))
        })
      }
      .background(Color.Magenta)
      .padding(16.dp)) {
      Row() {
        Icon(Icons.Outlined.Person, contentDescription = null, tint = Color.White)
        Spacer(modifier = Modifier.width(8.dp))
        Text(text = personName, color = Color.White, fontSize = 18.sp)
      }
    }
    DropdownMenu(
      expanded = isContextMenuVisible, onDismissRequest = {
        isContextMenuVisible = false
      }, offset = pressOffset.copy(
        y = pressOffset.y - itemHeight
      )
    ) {
      dropdownItems.forEach {
        DropdownMenuItem(onClick = {
          onItemClick(it)
          isContextMenuVisible = false
        }) {
          Text(text = it.text)
        }
      }
    }
  }
}

Add a DropdownMenuItem for each item in the list

Once you have created your list of items, you can add a DropdownMenuItem for each item in the list. This will allow the user to select an item from the dropdown menu. To do this, you can use the map function to create a DropdownMenuItem for each item in the list.

fun ComposeContextDropDownExampleUI() {
  val context = LocalContext.current
  LazyColumn(
    modifier = Modifier
      .fillMaxSize()
      .padding(16.dp),
    verticalArrangement = Arrangement.spacedBy(16.dp)
  ) {
    items(
      listOf(
        "Surya",
        "Morris",
        "Shaw",
        "Gill",
        "Jane",
        "Alex",
        "Jake",
        "Surya",
        "Surya",
      )
    ) {
      PersonItem(
        personName = it, dropdownItems = listOf(
          DropDownItem("Edit"),
          DropDownItem("Delete"),
          DropDownItem("Share"),
        ), onItemClick = {
          Toast.makeText(context, it.text, Toast.LENGTH_LONG).show()
        }, modifier = Modifier.fillMaxWidth()
      )
    }
  }
}

How to use this ComposeContextDropDownExampleUI

class MainActivity : ComponentActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContent {
      DropdownMenuComposeTheme {
        // A surface container using the 'background' color from the theme
        Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colors.background) {
          ComposeContextDropDownExampleUI()
        }
      }
    }
  }
}

Customize the appearance and behavior of the dropdown menu

To customize the appearance and behavior of the dropdown menu, you can use the DropdownMenuProperties parameter. This parameter allows you to set properties such as the width of the dropdown menu, the height of each item, and the color of the text. You can also set a callback function to be called when an item is selected from the dropdown menu.

This function can be used to update the state of your app or perform any other necessary actions. With these customization options, you can create a dropdown menu that fits perfectly with the design and functionality of your Jetpack Compose app.

Write A Comment