Comments 12
Я понимаю каскад на десктопе, но в смартфонах... Это же будет неудобно. зачем?
Мне понадобилось настройки приложения "спрятать", чтобы случайно пользователь не сбил. Но и к десктопу это все тоже применимо.
Возможно стоит еще немного подумать над интерфейсом? Потому что каскадное меню на смартфоне - это перебор.
PS: Эмулятор умеет записывать видео (ну или через adb shell screenrecord
тоже вариант).
Спасибо за советы! Но у меня стоит задача повторить приложение написанное на Android Xamarin (Фактически на Jave) на Котлине. А на Андроиде есть класс android.view.Menu, который позволяет сделать сложные вложенные меню, что и используется в приложении. Вот что-то подобное мне нужно реализовать на Compose. Я погуглил "Каскадные меню в Compose" и ничего приличного не обнаружил. Поэтому пришлось подумать самому. Важный момент, который удалось найти - использование параметра key у функции remember.
Запись видео на эмуляторе обязательно попробую.
Ну оно так-то достаточно просто делается... Пример, набросано за несколько минут:
@Composable
fun NestedMenuTest(name: String, modifier: Modifier = Modifier) {
var isExpanded by rememberSaveable { mutableStateOf(false) }
var isNestedExpanded by rememberSaveable { mutableStateOf(false) }
Box(modifier = modifier) {
IconButton(onClick = { isExpanded = true }) {
Icon(Icons.Default.MoreVert, contentDescription = null)
}
DropdownMenu(expanded = isExpanded, onDismissRequest = { isExpanded = false }) {
DropdownMenuItem(text = { Text(text = "Item 1") }, onClick = { })
DropdownMenuItem(
text = { Text(text = "Item 2") }, onClick = { isNestedExpanded = true },
trailingIcon = {
Icon(Icons.Default.MoreVert, contentDescription = null)
DropdownMenu(expanded = isNestedExpanded, onDismissRequest = { isNestedExpanded = false }) {
DropdownMenuItem(text = { Text(text = "Nested Item 1") }, onClick = { })
DropdownMenuItem(text = { Text(text = "Nested Item 2") }, onClick = { })
}
})
DropdownMenuItem(text = { Text(text = "Item 3") }, onClick = { })
}
}
}

Но Вы не скрываете меню предыдущего уровня. А именно в сокрытии основная проблема.
Намеренно. Для меня, как для пользователя, такой интерфейс (скрытие родителя) является дизориентирующим. Если сильно надо скрывать, то это делается легкой перекомпоновкой:
@Composable
fun NestedMenuTest(modifier: Modifier = Modifier) {
var isExpanded by rememberSaveable { mutableStateOf(false) }
var isNestedExpanded by rememberSaveable { mutableStateOf(false) }
Box(modifier = modifier) {
IconButton(onClick = { isExpanded = true }) {
Icon(Icons.Default.MoreVert, contentDescription = null)
}
DropdownMenu(expanded = isExpanded && !isNestedExpanded, onDismissRequest = { isExpanded = false }) {
DropdownMenuItem(text = { Text(text = "Item 1") }, onClick = { })
DropdownMenuItem(
text = { Text(text = "Item 2") }, onClick = { isNestedExpanded = true },
trailingIcon = {
Icon(Icons.Default.MoreVert, contentDescription = null)
})
DropdownMenuItem(text = { Text(text = "Item 3") }, onClick = { })
}
DropdownMenu(expanded = isNestedExpanded, onDismissRequest = { isNestedExpanded = false }) {
DropdownMenuItem(text = { Text(text = "Nested Item 1") }, onClick = { })
DropdownMenuItem(text = { Text(text = "Nested Item 2") }, onClick = { })
}
}
}
Вы все несколько переусложняете.
Но в любом случае, такого рода решения не очень хороши с точки зрения юзабилити. По моему скромному мнению.
Признаю. Ваше решение элегантнее моего. Я в начале тоже пытался разместить все меню в одной функции, но, к сожалению, не догадался до:
expanded = isExpanded && !isNestedExpanded, onDismissRequest = { isExpanded = false }
Спасибо за обсуждение и идею. Надеюсь, что это поможет еще кому-нибудь, кроме меня
Честно говоря выглядит как штука ради штуки, когда то же самое воспроизводится и на обычных dropdown'ах без дополнительных штук. Особенно странно в композе видеть unstable в data class.
стиль котлин не соблюден
в дата классах методов быть не должно
код написан небрежно
статические методы и данные тоже доставляют удовольсвтвия
Готов согласится по поводу data
. Правда, если вместо data class ListMenu(..
написать просто class ListMenu(..
принципиально ни чего не изменится и все будет работать. По поводу стека
companion - ни чего лучшего не придумал. Но, повторюсь, что смысл статьи - просто дать работающий пример каскадного меню "бесконечной" вложенности тем, кто будет искать что-то подобное...
Каскадное меню в Jetpack Compose Kotlin