如何在 Compose 中将 Toolbar 的菜单图标变成溢出?
Scaffold(
topBar = {
TopAppBar(
title = {
Text(text = "LayoutsCodelab")
},
actions = {
IconButton(onClick = { /* doSomething() */ }) {
Icon(Icons.Filled.Favorite)
}
IconButton(onClick = { /* doSomething() */ }) {
Icon(Icons.Filled.Refresh)
}
IconButton(
onClick = { /* doSomething() */ }) {
Icon(Icons.Filled.Call)
}
}
)
},
bottomBar = {
BottomNavigationLayout()
}
) { innerPadding ->
PhotoCard(Modifier.padding(innerPadding))
}
我只希望工具栏菜单中的一个图标可见,其他图标添加到溢出菜单中,就像使用 app:showAsAction="never"
使用 xml 完成的那样
<item
android:id="@+id/action_sign_out"
android:title="@string/toolbar_sign_out"
app:showAsAction="never"/>
答案 0 :(得分:4)
受到 @jns
的回答的启发,我制作了一个 ActionMenu
可组合对象,它接受一个 ActionItemSpec
对象列表。并在必要时使用溢出菜单显示它们。我对 ActionItemSpec
建模有点像旧的 XML 菜单项条目,但添加了一个 onClick lambda。
是这样用的
@Preview
@Composable
fun PreviewActionMenu() {
val items = listOf(
ActionItemSpec("Call", Icons.Default.Call, ActionItemMode.ALWAYS_SHOW) {},
ActionItemSpec("Send", Icons.Default.Send, ActionItemMode.IF_ROOM) {},
ActionItemSpec("Email", Icons.Default.Email, ActionItemMode.IF_ROOM) {},
ActionItemSpec("Delete", Icons.Default.Delete, ActionItemMode.IF_ROOM) {},
)
TopAppBar(
title = { Text("App bar") },
navigationIcon = {
IconButton(onClick = {}) {
Icon(Icons.Default.Menu, "Menu")
}
},
actions = {
// show 3 icons including overflow
ActionMenu(items, defaultIconSpace = 3)
}
)
}
预览看起来像这样
完整的粘贴箱在这里:https://gist.github.com/MachFour/369ebb56a66e2f583ebfb988dda2decf
答案 1 :(得分:3)
您必须自己提供 OverFlowMenu,例如:
@Preview
@Composable
fun PreviewOverflowMenu() {
OverflowMenuTest()
}
@Composable
fun OverflowMenuTest() {
var showMenu by remember { mutableStateOf(false) }
TopAppBar(
title = { Text("Title") },
actions = {
IconButton(onClick = { /*TODO*/ }) {
Icon(Icons.Default.Favorite)
}
IconButton(onClick = { showMenu = !showMenu }) {
Icon(Icons.Default.MoreVert)
}
DropdownMenu(
expanded = showMenu,
onDismissRequest = { showMenu = false }
) {
DropdownMenuItem(onClick = { /*TODO*/ }) {
Icon(Icons.Filled.Refresh)
}
DropdownMenuItem(onClick = { /*TODO*/ }) {
Icon(Icons.Filled.Call)
}
}
}
)
}
编辑:针对 Compose 1.0.0-beta08 进行了更新
答案 2 :(得分:0)
我稍微修改了@jns 的答案,使其更加模块化和可重用。 这是可重用的溢出菜单:
@Composable
fun OverflowMenu(content: @Composable () -> Unit) {
var showMenu by remember { mutableStateOf(false) }
IconButton(onClick = {
showMenu = !showMenu
}) {
Icon(
imageVector = Icons.Outlined.MoreVert,
contentDescription = stringResource(R.string.more),
)
}
DropdownMenu(
expanded = showMenu,
onDismissRequest = { showMenu = false }
) {
content()
}
}
这就是它在 TopAppBar 中的使用方式:
TopAppBar(
title = {
Text(text = stringResource(R.string.my_title))
},
actions = {
OverflowMenu {
DropdownMenuItem(onClick = { /*TODO*/ }) {
Text("Settings")
}
DropdownMenuItem(onClick = { /*TODO*/ }) {
Text("Bookmarks")
}
}
}
)
如果需要,我们可以向 DropDownMenuItems 添加图标。这些项目也可以提取为可重用的组合物。如果您想在菜单上显示为图标化按钮的其他操作按钮(即显示为操作),则应将它们放在 OverflowMenu 之前。
TopAppBar(
title = {
Text(text = stringResource(R.string.bookmark))
},
actions = {
//This icon will be shown on the top bar, on the left of the overflow menu
IconButton(onClick = { /*TODO*/ }) {
Icon(Icons.Filled.FavoriteBorder, stringResource(R.string.cd_favorite_item))
}
OverflowMenu {
SettingsDropDownItem(onClick = { /*TODO*/ })
BookmarksDropDownItem(onClick = { /*TODO*/ })
}
}
)
.
@Composable
fun SettingsDropDownItem(onClick : () -> Unit) {
//Drop down menu item with an icon on its left
DropdownMenuItem(onClick = onClick) {
Icon(Icons.Filled.Settings,
contentDescription = stringResource(R.string.settings),
modifier = Modifier.size(24.dp))
Spacer(modifier = Modifier.width(8.dp))
Text(stringResource(R.string.settings))
}
}
@Composable
fun BookmarksDropDownItem(onClick : () -> Unit) {
//Drop down menu item with an icon on its left
DropdownMenuItem(onClick = onClick) {
Icon(painter = painterResource(R.drawable.ic_bookmark_filled),
contentDescription = stringResource(R.string.bookmark),
modifier = Modifier.size(24.dp))
Spacer(modifier = Modifier.width(8.dp))
Text(stringResource(R.string.bookmark))
}
}