Wed. Jan 15th, 2025

In Jetpack Compose, there’s no direct equivalent to the traditional Spinner widget from the View-based UI system. However, you can implement a dropdown menu using DropdownMenu or ExposedDropdownMenuBox, which serve a similar purpose.

Example of Dropdown Using DropdownMenu

This example demonstrates creating a dropdown menu where users can select an item.

import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

@Composable
fun SimpleSpinner() {
    var expanded by remember { mutableStateOf(false) }
    val items = listOf("Option 1", "Option 2", "Option 3")
    var selectedItem by remember { mutableStateOf(items[0]) }

    Column(
        modifier = Modifier
            .fillMaxWidth()
            .padding(16.dp)
    ) {
        Text(
            text = selectedItem,
            modifier = Modifier
                .fillMaxWidth()
                .clickable { expanded = true }
                .padding(16.dp),
            style = MaterialTheme.typography.bodyLarge
        )

        DropdownMenu(
            expanded = expanded,
            onDismissRequest = { expanded = false },
            modifier = Modifier.fillMaxWidth()
        ) {
            items.forEach { label ->
                DropdownMenuItem(
                    text = { Text(label) },
                    onClick = {
                        selectedItem = label
                        expanded = false
                    }
                )
            }
        }
    }
}

Example of ExposedDropdownMenuBox

ExposedDropdownMenuBox provides a more modern and Material 3-compliant dropdown.

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ExposedDropdownMenuExample() {
    val items = listOf("Option 1", "Option 2", "Option 3")
    var expanded by remember { mutableStateOf(false) }
    var selectedItem by remember { mutableStateOf(items[0]) }

    ExposedDropdownMenuBox(
        expanded = expanded,
        onExpandedChange = { expanded = !expanded }
    ) {
        TextField(
            value = selectedItem,
            onValueChange = {},
            readOnly = true,
            label = { Text("Select an option") },
            trailingIcon = {
                ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded)
            },
            modifier = Modifier.menuAnchor()
        )

        ExposedDropdownMenu(
            expanded = expanded,
            onDismissRequest = { expanded = false }
        ) {
            items.forEach { selectionOption ->
                DropdownMenuItem(
                    text = { Text(selectionOption) },
                    onClick = {
                        selectedItem = selectionOption
                        expanded = false
                    }
                )
            }
        }
    }
}

Key Features

  1. DropdownMenu:
  • Flexible and customizable.
  • Can be used in various scenarios, not limited to “selectable” menus.
  1. ExposedDropdownMenuBox:
  • Specifically designed for dropdown menus.
  • Automatically aligns menus with TextFields and provides Material styling.
  1. State Management:
  • Manage expanded state using remember.
  • Track selected items dynamically.

When to Use

  • Use DropdownMenu for highly custom scenarios.
  • Use ExposedDropdownMenuBox for standard dropdowns, ensuring consistency with Material Design principles.

These composables allow you to build dropdowns in Jetpack Compose with the flexibility to style them however you need.

By Rajashekar

I’m (Rajashekar) a core Android developer with complimenting skills as a web developer from India. I cherish taking up complex problems and turning them into beautiful interfaces. My love for decrypting the logic and structure of coding keeps me pushing towards writing elegant and proficient code, whether it is Android, PHP, Flutter or any other platforms. You would find me involved in cuisines, reading, travelling during my leisure hours.

Leave a Reply

Your email address will not be published. Required fields are marked *