OptionsMenu 在方向更改时从片段中消失

OptionsMenu disappears from fragment on orientation change

选项菜单中的图标工作正常,但当您通过旋转屏幕改变方向时,图标会消失。

class SingleRecipeFragment : Fragment() {

    private lateinit var viewModel: SingleRecipeViewModel
    private lateinit var viewModelFactory: SingleRecipeViewModelFactory

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val binding: FragmentSingleRecipeBinding = DataBindingUtil.inflate(inflater,
            R.layout.fragment_single_recipe, container, false)
        val args =
            SingleRecipeFragmentArgs.fromBundle(
                requireArguments()
            )

        val application = requireNotNull(this.activity).application

        viewModelFactory =
            SingleRecipeViewModelFactory(
                args.recipeIndex, application
            )
        viewModel = ViewModelProvider(this,viewModelFactory)
            .get(SingleRecipeViewModel::class.java)

        binding.singleRecipeViewModel = viewModel
        binding.lifecycleOwner = this

        viewModel.curRecipe.observe(viewLifecycleOwner, Observer {
            (requireActivity() as MainActivity).toolbar.title = it?.title
        })

        //Toast.makeText(context, "Recipe Number: ${args.recipeIndex}",Toast.LENGTH_LONG).show()
        setHasOptionsMenu(true)
        return binding.root
    }

    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        super.onCreateOptionsMenu(menu, inflater)
        inflater.inflate(R.menu.single_recipe_menu, menu)

        viewModel.curRecipe.observe(viewLifecycleOwner, Observer {
            val favIconDrawable: Int = if (it!!.favorite) R.drawable.ic_baseline_star_filled_24
            else R.drawable.ic_baseline_star_border_24
            menu.findItem(R.id.favorite).setIcon(favIconDrawable)
        })
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        when (item.itemId) {
            R.id.share -> viewModel.shareSuccess(this.requireActivity())
            R.id.favorite -> viewModel.toggleFavorite()
        }
        return super.onOptionsItemSelected(item)
    }
}

菜单布局如下:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/share"
        android:enabled="true"
        android:icon="@drawable/ic_baseline_share_24"
        android:title="Share"
        android:visible="true"
        app:showAsAction="ifRoom" />
    <item
        android:id="@+id/favorite"
        android:enabled="true"
        android:icon="@drawable/ic_baseline_star_border_24"
        android:title="Share"
        android:visible="true"
        app:showAsAction="ifRoom" />
</menu>

此片段由传入 recipeID 值的 NavigationUI 从另一个片段启动。我试过在这个片段的 onResume 中使用 setHasOptionsMenu(true) 但它没有效果。知道为什么 optionsMenu 不持久吗?

似乎在 MainActivity 的 onCreate() 方法中使用 setSupportActionBar(toolbar) 解决了 optionsMenu 不持久的问题。但是,这打破了我用来在片段 windows.

上显示标题的方法

工具栏属于 Activity,不属于片段。因此,当方向更改后重新创建视图时,工具栏将设置为应用程序标题。当片段首次加载时不会发生这种情况,因为标题是由片段的 onCreate() 设置的。因此,解决方案是将自定义标题移动到片段的 onResume(),以便每次在屏幕上显示视图时重置它。

我正在像这样设置片段中的标题,因为如果我让导航控制器使用 navigation.xml 中的标签来设置标题,当片段加载到自定义工具栏布局的位置时,我会得到一个奇怪的行为正在被新的片段标题替换,并在右侧闪烁。

所以这个解决方案的 boiled-down 代码是:

片段:

class SingleRecipeFragment : Fragment() {

    override fun onCreateView(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setHasOptionsMenu(true)
    }

    override fun onResume() {
        super.onResume()
        /** This will reset your title every time the fragment is redrawn **/
        (requireActivity() as MainActivity).toolbar.title = "Some Custom Title"
    }

    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        super.onCreateOptionsMenu(menu, inflater)
        inflater.inflate(R.menu.single_recipe_menu, menu)
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        when (item.itemId) {
            R.id.share -> someMethodYouWantToRun()
            R.id.favorite -> someOtherMethod()
        }
        return super.onOptionsItemSelected(item)
    }
}

在您的 Activity 的 onCreate() 中,调用:

setSupportActionBar(toolbar)

这是为选项菜单扩充的菜单布局资源文件(与问题中的内容没有变化):

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/share"
        android:enabled="true"
        android:icon="@drawable/ic_baseline_share_24"
        android:title="Share"
        android:visible="true"
        app:showAsAction="ifRoom" />
    <item
        android:id="@+id/favorite"
        android:enabled="true"
        android:icon="@drawable/ic_baseline_star_border_24"
        android:title="Share"
        android:visible="true"
        app:showAsAction="ifRoom" />
</menu>