Меню DropdownMenu

Последнее обновление: 02.04.2024

Компонент DropdownMenu позволяет компактным образом разместить ряд вариантов для выбора пользователем - некий аналог контекстного меню. DropdownMenu немного похож на всплывающее окно - он может быть отображаться, а может быть скрыт. DropdownMenu сам по себе не занимает места в разметке и отображается поверх остального контента. Обычно DropdownMenu размещается в контейнере Box, хотя это необязательное требование.

Функция компонента принимает следующие параметры:

@Composable
fun DropdownMenu(
    expanded: Boolean,
    onDismissRequest: () -> Unit,
    modifier: Modifier = Modifier,
    offset: DpOffset = DpOffset(0.dp, 0.dp),
    scrollState: ScrollState = rememberScrollState(),
    properties: PopupProperties = PopupProperties(focusable = true),
    shape: Shape = MenuDefaults.shape,
    containerColor: Color = MenuDefaults.containerColor,
    tonalElevation: Dp = MenuDefaults.TonalElevation,
    shadowElevation: Dp = MenuDefaults.ShadowElevation,
    border: BorderStroke? = null,
    content: @Composable ColumnScope.() -> Unit
): Unit

Параметры функции компонента:

  • expanded: значение типа Boolean, которое устанавливает, будет ли меню отображаться (значение true) или будет скрыто (значение false)

  • onDismissRequest: представляет функцию-обработчик типа () -> Unit, которая вызывается, когда пользователь нажимает на область вне меню для его закрытия

  • modifier: представляет объект Modifier, который определяет модификаторы кнопки

  • offset: объект типа DpOffset, который определяет смещения позиции меню относительно положения по умолчанию. По умолчанию равно DpOffset(0.dp, 0.dp)

  • scrollState: значение типа ScrollState, которое применяется для настройки вертикальной прокрутки элементов.

  • properties: объект типа PopupProperties, который задает дополнительные свойства меню. По умолчанию равно PopupProperties(focusable = true)

  • shape: форма меню в виде объекта Shape.

  • containerColor: цвет контейнера.

  • tonalElevation: эффект анимации при нажатии на элемент меню.

  • shadowElevation: высота тени.

  • border: параметры границы в виде объекта BorderStroke.

  • content: содержимое меню в виде столбца компонентов. Обычно представляет набор компонентов типа DropdownMenuItem.

Определим простейшее меню DropdownMenu:

package com.example.helloapp

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material3.Divider
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Text
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            var expanded by remember { mutableStateOf(false) }

            Box {
                IconButton(onClick = { expanded = true }) {
                    Icon(Icons.Default.MoreVert, contentDescription = "Показать меню")
                }
                DropdownMenu(
                    expanded = expanded,
                    onDismissRequest = { expanded = false }
                ) {
                    Text("Скопировать", fontSize=18.sp, modifier = Modifier.padding(10.dp))
                    Text("Вставить", fontSize=18.sp, modifier = Modifier.padding(10.dp))
                    Divider()
                    Text("Настройки", fontSize=18.sp, modifier = Modifier.padding(10.dp))
                }
            }
        }
    }
}

Здесь для управления отображением меню определена переменная expanded, и ее значение привязано к параметру expanded компонента DropdownMenu. При нажатии на кнопку IconButton эта переменная получает значение true, и меню отображается на экране.

DropdownMenu в Jetpack Compose и Kotlin в Android

Само меню состоит из трех компонентов Text. Между предпоследним и последним компонентами располагается элемент Divider, который просто для красоты разделяет пункты меню горизонтальной линией.

При нажатии пользователем на область вне меню, срабатывает функция параметра onDismissRequest компонента DropdownMenu. В этой функции переменная expanded получает значение false, и меню скрывается.

DropdownMenuItem

Обычно элементы меню DropdownMenu предоставляют компонент DropdownMenuItem:

@Composable
fun DropdownMenuItem(
    text: @Composable () -> Unit,
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    leadingIcon: (@Composable () -> Unit)? = null,
    trailingIcon: (@Composable () -> Unit)? = null,
    enabled: Boolean = true,
    colors: MenuItemColors = MenuDefaults.itemColors(),
    contentPadding: PaddingValues = MenuDefaults.DropdownMenuItemContentPadding,
    interactionSource: MutableInteractionSource? = null
): Unit

Параметры функции компонента:

  • text: устанавливает содержимое компонента

  • onClick: представляет функцию-обработчик нажатия меню

  • modifier: предствляет объект Modifier, который определяет модификаторы компонента

  • leadingIcon: иконча, которая отображается в начале компонента

  • trailingIcon: иконча, которая отображается в конце компонента

  • enabled: значение типа Boolean устанавливает, доступен ли компонент для нажатия (значение true) или нет (значение false)

  • colors: цветовые настройки меню

  • contentPadding: объект типа PaddingValues, который устанавливает отступы между границами компонента и его содержимым. По умолчанию равно MenuDefaults.DropdownMenuItemContentPadding

  • interactionSource: представляет объект типа MutableInteractionSource, который устанавливает поток взаимодействий для кнопки. Значение по умолчанию - remember { MutableInteractionSource() }

Используем в качестве пунктов меню DropdownMenuItem:

package com.example.helloapp

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Box
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material3.Divider
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Text

import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            var expanded by remember { mutableStateOf(false) }

            Box {
                IconButton(onClick = { expanded = true }) {
                    Icon(Icons.Default.MoreVert, contentDescription = "Показать меню")
                }
                DropdownMenu(
                    expanded = expanded,
                    onDismissRequest = { expanded = false }
                ) {
                    DropdownMenuItem(
                        onClick = { },
                        text = { Text("Скопировать") }
                    )
                    DropdownMenuItem(
                        onClick = { },
                        text = {Text("Вставить")}
                    )
                    Divider()
                    DropdownMenuItem(
                        onClick = { },
                        text = {Text("Настройки")}
                    )
                }
            }
        }
    }
}

Обработка выбора пунктов меню

Если пункт меню представлен компонентом DropdownMenuItem, то мы можем определить обработку выбора пункта с помощью параметра onClick:

ackage com.example.helloapp

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material3.Divider
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Text

import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.unit.sp

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            var expanded by remember { mutableStateOf(false) }
            var selectedOption by remember { mutableStateOf("") }
            Box {
                Row {
                    IconButton(onClick = { expanded = true }) {
                        Icon(Icons.Default.MoreVert, contentDescription = "Показать меню")
                    }
                    Text("Выбран пункт: $selectedOption", fontSize = 28.sp)
                }
                DropdownMenu(
                    expanded = expanded,
                    onDismissRequest = { expanded = false }
                ) {
                    DropdownMenuItem(
                        onClick = { selectedOption = "Copy" },
                        text = { Text("Скопировать") }
                    )
                    DropdownMenuItem(
                        onClick = { selectedOption = "Paste" },
                        text = { Text("Вставить") }
                    )
                    Divider()
                    DropdownMenuItem(
                        onClick = { selectedOption = "Settings" },
                        text = { Text("Настройки") }
                    )
                }
            }
        }
    }
}

Здесь по нажатию на любой пункт меню в обработчике нажатия передаем переменной selectedOption соответствующее значение.

Определение позиции

Если нас не устраивает начальная позиция DropdownMenu, то мы можем ее сместить с помощью параметра offset. Он представляет объект DpOffset, который имеет два свойства: x (смещение по горизонтали) и y (смещение по вертикали). Оба свойства принимают значения в единицах dp:

package com.example.helloapp

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Box
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material3.Divider
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Text

import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.unit.DpOffset
import androidx.compose.ui.unit.dp

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            var expanded by remember { mutableStateOf(false) }
            var selectedOption by remember { mutableStateOf("") }
            Box {
                IconButton(onClick = { expanded = true }) {
                    Icon(Icons.Default.MoreVert, contentDescription = "Показать меню")
                }
                DropdownMenu(
                    expanded = expanded,
                    onDismissRequest = { expanded = false },
                    offset = DpOffset(x = 20.dp, y = 10.dp)
                ) {
                    DropdownMenuItem(
                        onClick = {},
                        text = { Text("Скопировать") }
                    )
                    DropdownMenuItem(
                        onClick = {  },
                        text = { Text("Вставить") }
                    )
                    Divider()
                    DropdownMenuItem(
                        onClick = { },
                        text = { Text("Настройки") }
                    )
                }
            }
        }
    }
}

В данном случае строка

offset = DpOffset(x = 20.dp, y = 10.dp)

Позволяет задать смещение меню на 20 пикселей вправо и на 10 пикселей вниз

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850