Android Fragment 顶部菜单右上角添加删除/搜索按钮

更新日期: 2023-06-02 阅读次数: 1104 字数: 577 分类: Android

例如,我想在 Android APP 首页顶部显示搜索按钮,在详情页顶部显示删除按钮。

叫 Menu 还是 Top App Bar

搜素 Android Menu

https://developer.android.com/develop/ui/views/components/menus

在官方文档里可以看到:

  • XML View 中称之为 Menu
  • Jetpack Compose 中称之为 Top App Bar

Android 菜单

Activity 中添加还是 Fragment 中添加

You can declare items for the options menu from either your Activity subclass or a Fragment subclass.

Activity 和 Fragment 中都可以添加。

If both your activity and fragment(s) declare items for the options menu, they are combined in the UI.

如果同时在 Activity 和 Fragment 添加了 menu,会把菜单项合并一起显示。也就会出现下面说明的重复显示的问题,需要选择性使用。

The activity's items appear first, followed by those of each fragment in the order in which each fragment is added to the activity. If necessary, you can re-order the menu items with the android:orderInCategory attribute in each you need to move.

先显示 Activity 中添加的菜单项,然后显示 Fragment 中添加的菜单项。但是可以重新排序。

To specify the options menu for an activity, override onCreateOptionsMenu() (fragments provide their own onCreateOptionsMenu() callback).

这个过时了,官方文档的描述过时了就很坑。Android API 发展太快了,到处都是过时的参考资料,ChatGPT 给出的代码也是过时的。

Kotlin 实现代码

首先注释掉 MainActivity 中的 onCreateOptionsMenu,否则后续在 fragment 中添加 menu 的时候,会出现两个相同的图标。

/*
override fun onCreateOptionsMenu(menu: Menu): Boolean {
	// Inflate the menu; this adds items to the action bar if it is present.
	menuInflater.inflate(R.menu.main, menu)
	return true
}
 */

fragment 中实现设置 menu 的逻辑。例如:

隐藏搜索图标,分条件决定是否隐藏删除图标。

class YourFragment: Fragment(..) {

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        setupMenu()
    }

    private fun setupMenu() {
        (requireActivity() as MenuHost).addMenuProvider(object : MenuProvider {
            override fun onPrepareMenu(menu: Menu) {
               // Handle for example visibility of menu items
			   menu.findItem(R.id.action_search).isVisible = false
			   if (id == 0L) {
			       menu.findItem(R.id.action_delete).isVisible = false
			   }
            }

            override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
                menuInflater.inflate(R.menu.your_menu, menu)
            }

            override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
                // Validate and handle the selected menu item
				// You'll want to return true only if you've actually handled the menu item 
				// 注意:由自己代码处理的按钮逻辑,可以 return true; 否则需要 return false。
				// 如果都 return true,会造成顶部返回按钮失效,所以默认是 return false。
                when (menuItem.itemId) {
                    R.id.action_delete -> {
                        // 删除操作
						// TODO: do something
                        return true
                    }
                }

                return false
            }
        }, viewLifecycleOwner, Lifecycle.State.RESUMED)
    }
}

废弃的 onCreateOptionsMenu

https://developer.android.com/reference/android/app/Fragment#onCreateOptionsMenu(android.view.Menu,%20android.view.MenuInflater)

Deprecated in API level 28

还没用上就废弃了。

参考

  • https://medium.com/tech-takeaways/how-to-migrate-the-deprecated-oncreateoptionsmenu-b59635d9fe10

关于作者 🌱

我是来自山东烟台的一名开发者,有敢兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊, 查看更多联系方式