the*_*ear 11 android android-menu android-fragments
大约一个月前,Android 团队弃用了onCreateOptionsMenu和onOptionsItemSelected,以及setHasOptionsItemMenu. 不幸的是,这破坏了我的所有代码。
我的应用程序有很多片段,当用户导航到它们时,我总是确保菜单项会消失并在返回时重新出现,代码如下:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
}
Run Code Online (Sandbox Code Playgroud)
override fun onPrepareOptionsMenu(menu: Menu) {
super.onPrepareOptionsMenu(menu)
menu.clear()
}
Run Code Online (Sandbox Code Playgroud)
这段代码运行良好并且非常简单。现在 Android 团队已弃用(为什么?)setHasOptionsMenu,我无法重新创建此代码。
我了解用于扩充菜单项和处理菜单项单击事件的新语法,尽管我一生都无法弄清楚如何将菜单隐藏在片段中,然后使用新菜单在导航返回时再次显示它提供商 API。
这是我尝试过的:
导航到片段:
if (supportFragmentManager.backStackEntryCount == 0) {
supportFragmentManager.commit {
replace(R.id.activityMain_primaryFragmentHost, NewProjectFragment.newInstance(mainSpotlight != null))
addToBackStack(null)
}
}
Run Code Online (Sandbox Code Playgroud)
getRootMenuProvider接口中的函数ActivityFragment:
interface ActivityFragment {
val title: String
companion object {
fun getRootMenuProvider() = object : MenuProvider {
override fun onPrepareMenu(menu: Menu) {
for (_menuItem in menu.children) {
_menuItem.isVisible = false
}
}
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
}
override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
return false
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
使用该getRootMenuProvider功能:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val menuHost: MenuHost = requireActivity()
menuHost.addMenuProvider(ActivityFragment.getRootMenuProvider())
}
Run Code Online (Sandbox Code Playgroud)
MainActivity(尝试将菜单项恢复到之前的状态):
override fun onPrepareOptionsMenu(menu: Menu): Boolean {
for (_menu in menu.children) {
_menu.isVisible = true
}
return super.onPrepareOptionsMenu(menu)
}
override fun onBackPressed() {
super.onBackPressed()
findViewById<BottomNavigationView>(R.id.activityMain_bottomNavigationView)?.visibility = View.VISIBLE
invalidateOptionsMenu()
}
Run Code Online (Sandbox Code Playgroud)
这会隐藏片段中的项目,但导航回来后这些项目仍然保持隐藏状态,直到用户通过旋转屏幕或执行类似操作重新加载活动。
如何使用新的菜单提供程序 API隐藏片段中的菜单项并在导航返回时重新显示它们?
ian*_*ake 20
短期
一切都“崩溃”的原因是因为您假设menu.clear()片段菜单调用的调度是在您的活动添加了自己的菜单项之后发生的。现在,当您的活动调用时,片段会经历菜单调用的调度,super.onCreateOptionsMenu()或者super.onPrepareOptionsMenu()您经常可以通过将其作为您的覆盖调用的最后一个而不是第一个来“解决”您的问题。
长期
事实上,您做错了很多:由 Activity 控制的全局菜单是共享资源,任何单独的片段都不应该手动清除整个菜单。这会破坏活动菜单项、子片段菜单项以及其他片段的菜单项。只有膨胀某些菜单项的组件才应该接触这些特定的菜单项。
因此,要解决您的问题,您应该遵循Activity 1.4.0-alpha01 发行说明(该版本添加了MenuHost和MenuProvider集成到 Activity 层中:
AndroidX
ComponentActivity[及其子类FragmentActivity和AppCompatActivity] 现在实现了该MenuHost接口。这允许任何组件通过向活动ActionBar添加实例来添加菜单项。每个菜单项都可以选择添加一个生命周期,该生命周期将根据状态自动控制这些菜单项的可见性,并在销毁时处理删除。MenuProviderMenuProviderLifecycleMenuProviderLifecycle
他们继续展示其在片段中的用法示例:
Run Code Online (Sandbox Code Playgroud)/** * Using the addMenuProvider() API in a Fragment **/ ExampleFragment : Fragment(R.layout.fragment_example) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { // The usage of an interface lets you inject your own implementation val menuHost: MenuHost = requireActivity() // Add menu items without using the Fragment Menu APIs // Note how we can tie the MenuProvider to the viewLifecycleOwner // and an optional Lifecycle.State (here, RESUMED) to indicate when // the menu should be visible menuHost.addMenuProvider(object : MenuProvider { override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) { // Add menu items here menuInflater.inflate(R.menu.example_menu, menu) } override fun onMenuItemSelected(menuItem: MenuItem): Boolean { // Handle the menu selection return true } }, viewLifecycleOwner, Lifecycle.State.RESUMED) }
这特别展示了三件事:
MenuProvider应该只触摸其菜单项。您永远不应该“清除所有菜单项”或任何影响其他组件菜单项的内容。addMenuProvider使用生命周期进行调用(在本例中,是片段视图的生命周期 - 即仅当片段视图在屏幕上时才存在),那么当片段视图被销毁时(当您的调用发生时),您将自动replace隐藏菜单项并在片段视图重新出现时(即弹出后堆栈时)自动重新显示。Lifecycle应该是创建和处理其自己的菜单项的片段。您的活动(可以添加自己的活动MenuProvider,如其他示例中所示)应该只添加活动整个生命周期中存在的菜单项(在所有片段上可见的项目)。| 归档时间: |
|
| 查看次数: |
6039 次 |
| 最近记录: |