You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

5.9 KiB

Context Menu in Compose for Desktop

What is covered

In this tutorial we will cover all aspects of work with Context Menu using the Compose UI framework.

Default context menu

There is out-of-the box context menu support for TextField and Selectable text.

To enable standard context menu for a TextField you just need to put it inside DesktopMaterialTheme:

import androidx.compose.desktop.DesktopMaterialTheme
import androidx.compose.material.Text
import androidx.compose.material.TextField
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.window.singleWindowApplication

@OptIn(ExperimentalComposeUiApi::class, androidx.compose.foundation.ExperimentalFoundationApi::class)
fun main() = singleWindowApplication(title = "Context menu") {
   DesktopMaterialTheme { //it is mandatory for Context Menu
       val text = remember {mutableStateOf("Hello!")}
       TextField(
           value = text.value,
           onValueChange = { text.value = it },
           label = { Text(text = "Input") }
       )
   }
} 

Standard context menu for TextField contains the following items based on text selection: Copy, Cut, Paste, Select All.

Enabling standard context menu for a Text component is similar - you just need to make it selectable:

import androidx.compose.desktop.DesktopMaterialTheme
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.material.Text
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.window.singleWindowApplication

@OptIn(ExperimentalComposeUiApi::class, androidx.compose.foundation.ExperimentalFoundationApi::class)
fun main() = singleWindowApplication(title = "Context menu") {
   DesktopMaterialTheme { //it is mandatory for Context Menu
        SelectionContainer {
            Text("Hello World!")
        }
   }
} 

Context menu for text contains just Copy action.

User-defined context menu

To enable additional context menu items for TextField and Text components, ContextMenuDataProvider and ContextMenuItem elements are used:

import androidx.compose.desktop.DesktopMaterialTheme
import androidx.compose.foundation.ContextMenuDataProvider
import androidx.compose.foundation.ContextMenuItem
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.material.Text
import androidx.compose.material.TextField
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.singleWindowApplication

@OptIn(ExperimentalComposeUiApi::class, androidx.compose.foundation.ExperimentalFoundationApi::class)
fun main() = singleWindowApplication(title = "Context menu") {
    DesktopMaterialTheme { //it is mandatory for Context Menu
        val text = remember {mutableStateOf("Hello!")}
        Column {
            ContextMenuDataProvider(
                items = {
                    listOf(
                        ContextMenuItem("User-defined Action") {/*do something here*/},
                        ContextMenuItem("Another user-defined action") {/*do something else*/}
                    )
                }
            ) {
                TextField(
                    value = text.value,
                    onValueChange = { text.value = it },
                    label = { Text(text = "Input") }
                )

                Spacer(Modifier.height(16.dp))

                SelectionContainer {
                    Text("Hello World!")
                }
            }
        }
    }
} 

In this example Text/TextField context menus will be extended with two additional items.

Context menu for an arbitrary area

There is a possibility to create a context menu for an arbitrary application window area. This is implemented using ContextMenuArea API that is similar to ContextMenuDataProvider.

import androidx.compose.foundation.ContextMenuDataProvider
import androidx.compose.foundation.ContextMenuItem
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.material.TextField
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.singleWindowApplication

@OptIn(ExperimentalComposeUiApi::class, androidx.compose.foundation.ExperimentalFoundationApi::class)
fun main() = singleWindowApplication(title = "Context menu") {
    MaterialTheme { //it is mandatory for Context Menu
        val text = remember {mutableStateOf("Hello!")}
        Column {
            ContextMenuDataProvider(
                items = {
                    listOf(
                        ContextMenuItem("User-defined Action") {/*do something here*/},
                        ContextMenuItem("Another user-defined action") {/*do something else*/}
                    )
                }
            ) {
                TextField(
                    value = text.value,
                    onValueChange = { text.value = it },
                    label = { Text(text = "Input") }
                )

                Spacer(Modifier.height(16.dp))

                SelectionContainer {
                    Text("Hello World!")
                }
            }
        }
    }
}

Right click on the Blue Square will show a context menu with two items