menu.xml 必须放在 res/menu/ 目录下,否则 MenuInflater 会抛 Resources$NotFoundException;android:id 和 android:title 是 item 标签的必需属性;app:showAsAction 值需正确使用 ifRoom、never、always 等,且必须用 app 命名空间。

menu.xml 文件该放哪个目录才生效
Android 的 menu.xml 必须放在 res/menu/ 目录下,否则 MenuInflater 找不到资源,调用 inflate() 时会直接抛 Resources$NotFoundException。这个路径是硬编码在系统里的,不能改名或挪到 res/layout/ 或 res/values/ 下。
- 新建目录:右键
res→New → Android Resource Directory→ 类型选menu - 文件名随意,但建议见名知意,比如
menu_main.xml、menu_detail.xml - 如果项目用了
productFlavors,可以按 flavor 新建src/flavorName/res/menu/,优先级高于主res/menu/
item 标签里哪些属性是必须写的
android:id 和 android:title 是实际可点击菜单项的最低要求。漏掉 android:id,后续在 onOptionsItemSelected() 里就无法用 itemId 区分点击了;没 android:title,文字不显示,用户根本不知道点什么。
-
android:id:必须是唯一整型资源 ID,推荐用@+id/action_save这种写法 -
android:title:支持字符串资源引用(@string/save)或直写("Save"),后者不利于多语言 -
android:icon不是必须的,但加了图标后,Toolbar 上才可能显示为 icon(取决于app:showAsAction) -
android:orderInCategory影响排序,但不设也不会报错,只是顺序由系统默认(通常按 XML 顺序)
showAsAction 属性值怎么选才不出问题
app:showAsAction 控制菜单项是否显示在 Toolbar 上,值选错会导致图标消失、溢出弹窗不出现,甚至整个菜单不响应点击。注意它属于 app 命名空间,不是 android: 开头。
-
ifRoom:有空间就显示图标,否则收进三点菜单 —— 最常用,适合操作频次高的项 -
never:一定不显示在 Toolbar,只出现在溢出菜单 —— 适合设置、帮助这类低频项 -
always:强制显示在 Toolbar —— 小心!可能导致图标被截断或布局错乱,官方已不推荐 -
withText:仅配合ifRoom或always使用,表示“图标+文字”,但文字常因空间不足被隐藏 - 错误写法:
android:showAsAction="ifRoom"(命名空间错)或app:showAsAction="collapse"(非法值)
为什么 onCreateOptionsMenu 没被调用或菜单不显示
最常见原因是 Activity 没设置 Toolbar 为 ActionBar,或者 setSupportActionBar() 被调晚了(比如放在 onResume() 里)。系统只有在 ActionBar 存在且启用时,才会触发菜单生命周期。
- 确认已在
onCreate()中调用setSupportActionBar(toolbar),且toolbar非 null - 检查 Activity 的主题是否禁用了 ActionBar,比如用了
Theme.AppCompat.Light.DarkActionBar是 OK 的,但Theme.AppCompat.NoActionBar必须手动 set -
onCreateOptionsMenu()返回false会导致菜单完全不加载,务必 return true - 如果用了 Fragment,别在 Fragment 里重写
onCreateOptionsMenu()却忘了调setHasOptionsMenu(true)
Toolbar 菜单本质是 ActionBar 的兼容实现,所有行为都绕不开这个前提。ID 冲突、主题覆盖、inflate 时机错位——这些地方一动就失效,比写逻辑代码还容易卡住。










