How to propagate outside click in DropdownMenu to outside UI elements?

65 views Asked by At

I have Row() of IconButtons and for each, I'd like to show DropdownMenu with options that are specific for a particular IconButton.

Screen

Case: The first icon button is clicked and DropdownMenu is shown. Then I click on the second icon button.

Desired behavior: the second icon button handles this click and replaces the content of the dropdown menu.

Actual behavior: The dropdown menu disappeared. The second button didn't handle this click.

Is there a more appropriate way to achieve the expected behavior:

  • clicking outside of DropdownMenu will be handled by a UI element that is outside of the menu; ?
@Composable
fun Screen1() {
    Column() {
        Row() {
            // Main function
            TopBarWithOptions()
        }

        // Add some space between top and bottom elements
        Row(modifier = Modifier.weight(1f)) { }

        TextButton(
            onClick = { Log.d(TAG, "Button1 is clicked") },
            colors = ButtonDefaults.buttonColors()
        ) { Text("Button1") }

        TextButton(
            onClick = { Log.d(TAG, "Button1 is clicked") },
            colors = ButtonDefaults.buttonColors()
        ) { Text("Button2") }
    }
}

@Composable
fun TopBarWithOptions() {

    // Define list of menu items for top bar icon 1
    val options1: List<@Composable () -> Unit> = listOf(
        {Text("1 option1")},
        {Text("1 option2")},
        {Text("1 option3")},
    )

    // Define list of menu items for top bar icon 2
    val options2: List<@Composable () -> Unit> = listOf(
        {Text("2 option1")},
        {Text("2 option2")},
        {Text("2 option3")},
    )

    // This is reference of content for DropDownMenu
    var activeOptions:(List<@Composable () -> Unit>)? by remember { mutableStateOf(null) }

    var showOptions by remember { mutableStateOf(false) }

    TopBarIcon(Icons.Default.Add, onClick = {
        Log.d("pablok", "click1")
        if (activeOptions == options1) {
            showOptions = !showOptions
        } else {
            activeOptions = options1
            showOptions = true
        }
    })

    TopBarIcon(Icons.Default.Call, onClick = {
        Log.d("pablok", "click3")
        if (activeOptions == options2) {
            showOptions = !showOptions
        } else {
            activeOptions = options2
            showOptions = true
        }
    })

    DropdownMenu(
        expanded = showOptions,
        onDismissRequest = {
            showOptions = false
        }
    )
    {
        activeOptions?.let { items ->
            items.forEach { it() }
        }
    }
}


0

There are 0 answers