【问题标题】:How to change AppBar Menu in Jetpack Compose?如何更改 Jetpack Compose 中的 AppBar 菜单?
【发布时间】:2020-10-25 16:31:57
【问题描述】:

我想知道如何更改 Jetpack Compose 中的 Appbar 菜单。

Fragment 的世界中,要实现这一点就是这样做:

class SampleFragment : Fragment() {
    override fun onCreate(context: Context) {
        super.onCreate(context)
        setHasOptionsMenu(true)
    }

    // Set the R.menu.sampleMenu in the AppBar
    override fun onCreateOptionsMenu(menu: Menu) {
        ...
        menuInflater.inflate(R.menu.sampleMenu, menu)
    }

    // To handle clicks on the menu
    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        // Check id of menu item and process as follow
    }
...
}

我想知道如何在 Compose 中做同样的事情。我想有这样的:

// Have a top level state which could be set 
var menu by remember { mutableStateOf(emptyList<Menu>()) }

....
TopAppBar {
    ....
    menu.forEach {
        TextButton(...)
    }
}

....

//and then on my content ill set the `menu` to a value
onCommit {
    menu = listOf(Menu1, Menu2, Menu3, ...)
}

我想知道这是否是正确的方法,或者是否有更好的方法。

我很想得到一些意见和建议,非常感谢。

【问题讨论】:

  • “在屏幕之间导航时这样做也有问题”——我们不知道您是如何执行导航的。至少在 Jetpack Navigation 组件支持 Compose 之前,我见过的最常见的方法是“我们在什么屏幕上”有一个顶级状态。对该状态的更改会驱动哪些可组合项呈现屏幕,包括应用栏菜单中的项目。
  • 但是当前屏幕仍然如何捕获点击事件?如果只有顶级状态保持是当前屏幕的标识符?
  • 一些可组合物负责您的每个屏幕。将状态作为参数传递给那些可组合的函数。这个想法是,对于所有需要状态的分支,状态应该位于最高的公共位置。
  • 我有点理解,但有点困惑。你能告诉我一些示例代码吗?我真的很感激。
  • 你找到解决办法了吗?

标签: android android-jetpack-compose


【解决方案1】:

有一个名为 DropdownMenu 的组件,您可以在此处阅读:https://developer.android.com/reference/kotlin/androidx/compose/material/package-summary#dropdownmenu

请注意,您不应将其包装在按钮中,有一个名为 toggle 的参数将是打开菜单的按钮。

还有一个 DropdownMenuItem,其样式由 Material Design 规范定义: https://developer.android.com/reference/kotlin/androidx/compose/material/package-summary#dropdownmenuitem

关于导航,我认为完全是另一回事,如果您对此有任何疑问,请发布其他问题的详细信息。

这是一个小例子:

var menuExpanded by remember { mutableStateOf(false) }
DropdownMenu(
    toggle = {
        TextButton({ menuExpanded = !menuExpanded }) {
            Text("Open menu", color = Color.White)
        }
    },
    expanded = menuExpanded,
    onDismissRequest = {
        menuExpanded = false
    },
) {
    DropdownMenuItem(onClick = {}) {
        Text("First item")
    }
    DropdownMenuItem(onClick = {}) {
        Text("Second item")
    }
    DropdownMenuItem (onClick = {}) {
        Text("Third item")
    }
}

编辑:由于您评论说您的问题在于跨屏幕共享应用栏,重要的是要指出这将按照您实现它的方式进行,例如,在下面的代码中,我会有不同的应用栏对于不同的屏幕,问题就会得到解决,当然,这是一个非常简单的示例,对于多个屏幕来说是不可行的。但是那里有关于在 Compose 中处理导航的内容,如果您对此有任何疑问,您可以提出其他问题来确定您所需要的范围。

val currentScreen by viewModel.currentScreen.observeAsState(Screen.HOME)
when (currentScreen) {
    Screen.HOME -> Scaffold(/* topBar = ... */) {
        // Home body
    }
    Screen.PROFILE -> Scaffold(/* topBar = ... */) {
        // Profile body
    }
    Screen.CHAT -> Scaffold(/* topBar = ... */) {
        // Chat body
    }
}

【讨论】:

  • 我认为您的回答与我的问题无关...嗯..
  • 那我没看懂你的问题,我以为你问的是如何制作菜单,我给你看了,你能解释一下你的问题吗?
  • 它实际上与制作菜单无关。它正在设置它们并根据当前显示的屏幕处理其onClick
  • 所以比如ScreenA必须有MenuA,ScreenB必须有MenuB,以此类推……既然AppBar是跨​​屏共享的,那么如何根据屏幕设置这些菜单,如何设置处理他们的onClick 事件...
  • 因此,应用栏正在屏幕之间共享,因为这是您使其工作的方式,如果您使用 Scaffold 并将导航逻辑放在正文中,则应用栏确实会被共享,但是如果您将整个脚手架包装在导航逻辑中,那么每个屏幕都会有一个应用栏,我将更新我的答案以涵盖这种情况
猜你喜欢
  • 2022-12-14
  • 1970-01-01
  • 2021-07-10
  • 2022-11-06
  • 1970-01-01
  • 2021-10-27
  • 2023-02-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多