You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android 12 type_floating类型ActionMode菜单项仅显示标题不显示图标

问题原因

Android 12(API 31)调整了浮动类型ActionMode(即TYPE_FLOATING)的菜单默认渲染规则:系统给浮动操作模式的弹出菜单默认关闭了可选图标显示开关,即使手动给MenuItem设置SHOW_AS_ACTION_ALWAYS和图标资源,系统也会默认隐藏图标仅展示文本,这也是低版本正常、Android 12异常的核心原因。
另外你贴的代码存在明显笔误:给red菜单项赋值后,后续调用setShowAsAction、setIcon的是未定义的note变量,这部分会直接触发运行时异常,优先修正。

异常效果参考:
Android12浮动ActionMode图标不显示效果

修复方案

第一步:补全所有菜单项的基础配置

把setFloatingMenuClickListeners方法里的配置补全,给每个菜单项单独设置展示规则和对应图标,修正变量名错误:

private void setFloatingMenuClickListeners(Menu menu) {
    MenuItem red = menu.findItem(R.id.red_view);
    red.setOnMenuItemClickListener(actionModeClick);
    red.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
    red.setIcon(R.drawable.icon_red);

    MenuItem orange = menu.findItem(R.id.orange_view);
    orange.setOnMenuItemClickListener(actionModeClick);
    orange.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
    orange.setIcon(R.drawable.icon_orange);

    MenuItem pink = menu.findItem(R.id.pink_view);
    pink.setOnMenuItemClickListener(actionModeClick);
    pink.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
    pink.setIcon(R.drawable.icon_pink);
}

把上面的图标资源替换成你项目里实际的资源id即可。

第二步:兼容Android 12的图标隐藏逻辑

两种方案二选一即可:

方案1:反射强制开启菜单图标显示(侵入性最低)

在ActionMode创建阶段,通过反射调用菜单内部方法强制打开图标显示开关,不需要修改主题配置:

@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
    menu.clear();
    mode.getMenuInflater().inflate(R.menu.menu_feature, menu);
    // Android 12+ 兼容处理
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        try {
            Method getMenuBuilder = mode.getClass().getDeclaredMethod("getMenuBuilder");
            getMenuBuilder.setAccessible(true);
            Object menuBuilder = getMenuBuilder.invoke(mode);
            if (menuBuilder != null) {
                Method setIconsVisible = menuBuilder.getClass()
                        .getDeclaredMethod("setOptionalIconsVisible", boolean.class);
                setIconsVisible.setAccessible(true);
                setIconsVisible.invoke(menuBuilder, true);
            }
        } catch (Exception ignored) {
            // 反射失败不影响核心功能,无需额外处理
        }
    }
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        mode.invalidateContentRect();
    }
    setFloatingMenuClickListeners(menu);
    return true;
}

把原来写在onActionModeStarted里的菜单初始化逻辑挪到onCreateActionMode里,避免系统提前渲染未配置完成的菜单,onActionModeStarted里直接调用super方法即可。

方案2:主题配置覆盖系统默认样式(无反射)

不想用反射的话,可以直接在App主题里覆盖浮动ActionMode的弹出菜单样式,强制开启图标显示:

<!-- 应用主主题 -->
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
    <!-- 其他原有主题属性保持不变 -->
    <item name="actionModePopupWindowStyle">@style/FixIconActionModePopup</item>
</style>

<style name="FixIconActionModePopup" parent="Widget.MaterialComponents.PopupWindow.FloatingActionMode">
    <item name="android:popupMenuStyle">@style/ForceShowIconMenu</item>
</style>

<style name="ForceShowIconMenu" parent="Widget.AppCompat.PopupMenu">
    <item name="android:optionalIconsVisible">true</item>
</style>

如果项目已经配置过自定义的ActionMode样式,只需要把android:optionalIconsVisible属性加进去即可。

注意事项
  • 浮动ActionMode的菜单项图标建议使用24dp尺寸的资源,过大会被系统自动裁剪导致显示异常。
  • 所有菜单配置逻辑要在调用super.onActionModeStarted或者super.onCreateActionMode之前执行,否则系统会提前完成菜单渲染,配置不生效。

内容的提问来源于stack exchange,提问作者Kanika

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 09:57:29