简体   繁体   English

如何在ActionBar的“溢出”菜单中显示图标

[英]How To show icons in Overflow menu in ActionBar

I know it's not possible using the native API. 我知道使用本机API是不可能的。 Is there a workaround to implement that kind of view? 是否有解决方法来实现这种视图?

The previously posted answer is OK, generally speaking. 一般来说,之前发布的答案是可以的。 But it basically removes the default behaviour of the Overflow menu. 但它基本上删除了溢出菜单的默认行为。 Things like how many icons can be displayed on different screen-sizes and then they dropped off into the overflow menu when they can't be displayed. 可以在不同的屏幕尺寸上显示多少个图标,然后当它们无法显示时,它们会进入溢出菜单。 By doing the above you remove a lot of important functionality. 通过执行上述操作,您可以删除许多重要功能。

A better method would be to tell the overflow menu to display the icons directly. 更好的方法是告诉溢出菜单直接显示图标。 You can do this by adding the following code to your Activity. 您可以通过将以下代码添加到Activity来完成此操作。

@Override
public boolean onMenuOpened(int featureId, Menu menu)
{
    if(featureId == Window.FEATURE_ACTION_BAR && menu != null){
        if(menu.getClass().getSimpleName().equals("MenuBuilder")){
            try{
                Method m = menu.getClass().getDeclaredMethod(
                    "setOptionalIconsVisible", Boolean.TYPE);
                m.setAccessible(true);
                m.invoke(menu, true);
            }
            catch(NoSuchMethodException e){
                Log.e(TAG, "onMenuOpened", e);
            }
            catch(Exception e){
                throw new RuntimeException(e);
            }
        }
    }
    return super.onMenuOpened(featureId, menu);
}

In your menu xml, use the following syntax to nest menu, you will start getting the menu with icons 在菜单xml中,使用以下语法嵌套菜单,您将开始获取带有图标的菜单

<item
    android:id="@+id/empty"
    android:icon="@drawable/ic_action_overflow"
    android:orderInCategory="101"
    android:showAsAction="always">
    <menu>
        <item
            android:id="@+id/action_show_ir_list"
            android:icon="@drawable/ic_menu_friendslist"
            android:showAsAction="always|withText"
            android:title="List"/>
    </menu>
</item>

Tried this based on the previous answers and it works fine, at least with more recent versions of the support library (25.1): 基于之前的答案尝试了这一点并且它工作正常,至少在支持库的更新版本(25.1)中:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu_main, menu);

    if(menu instanceof MenuBuilder){
        MenuBuilder m = (MenuBuilder) menu;
        //noinspection RestrictedApi
        m.setOptionalIconsVisible(true);
    }

    return true;
}

You can make use of SpannableString 您可以使用SpannableString

public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu_tab, menu);

    MenuItem item = menu.findItem(R.id.action_login);
    SpannableStringBuilder builder = new SpannableStringBuilder("* Login");
    // replace "*" with icon
    builder.setSpan(new ImageSpan(this, R.drawable.login_icon), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    item.setTitle(builder);
}

The answer from Simon was very useful to me, so I want to share how I implemented it into the onCreateOptionsMenu -method as suggested: Simon的回答对我非常有用,所以我想分享我如何按照建议将其实现到onCreateOptionsMenu -method:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu items for use in the action bar
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.main_action_bar, menu);

    // To show icons in the actionbar's overflow menu:
    // http://stackoverflow.com/questions/18374183/how-to-show-icons-in-overflow-menu-in-actionbar
    //if(featureId == Window.FEATURE_ACTION_BAR && menu != null){
        if(menu.getClass().getSimpleName().equals("MenuBuilder")){
            try{
                Method m = menu.getClass().getDeclaredMethod(
                        "setOptionalIconsVisible", Boolean.TYPE);
                m.setAccessible(true);
                m.invoke(menu, true);
            }
            catch(NoSuchMethodException e){
                Log.e(TAG, "onMenuOpened", e);
            }
            catch(Exception e){
                throw new RuntimeException(e);
            }
        }
    //}

    return super.onCreateOptionsMenu(menu);
}

Building on @Desmond Lua's answer from above , I made a static method for using the drawable declared in XML in the dropdown, and ensuring that it's tinted color does not affect the Constant Drawable state. 基于@Desmond Lua从上面得到的答案,我创建了一个静态方法,用于在下拉列表中使用XML中声明的drawable,并确保它的着色颜色不会影响Constant Drawable状态。

    /**
 * Updates a menu item in the dropdown to show it's icon that was declared in XML.
 *
 * @param item
 *         the item to update
 * @param color
 *         the color to tint with
 */
private static void updateMenuWithIcon(@NonNull final MenuItem item, final int color) {
    SpannableStringBuilder builder = new SpannableStringBuilder()
            .append("*") // the * will be replaced with the icon via ImageSpan
            .append("    ") // This extra space acts as padding. Adjust as you wish
            .append(item.getTitle());

    // Retrieve the icon that was declared in XML and assigned during inflation
    if (item.getIcon() != null && item.getIcon().getConstantState() != null) {
        Drawable drawable = item.getIcon().getConstantState().newDrawable();

        // Mutate this drawable so the tint only applies here
        drawable.mutate().setTint(color);

        // Needs bounds, or else it won't show up (doesn't know how big to be)
        drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
        ImageSpan imageSpan = new ImageSpan(drawable);
        builder.setSpan(imageSpan, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        item.setTitle(builder);
    }
}

And using it would look something like this when used in an activity. 在活动中使用时,使用它会看起来像这样。 This could probably be even more elegant depending on your individual needs. 根据您的个人需求,这可能会更加优雅。

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu_activity_provider_connect, menu);
    int color = ContextCompat.getColor(this, R.color.accent_dark_grey);
    updateMenuWithIcon(menu.findItem(R.id.email), color);
    updateMenuWithIcon(menu.findItem(R.id.sms), color);
    updateMenuWithIcon(menu.findItem(R.id.call), color);
    return true;
}

Current best, but not accepted solution probably works on older platforms. 当前最好但不被接受的解决方案可能适用于较旧的平台。 Anyway in new AppCompat21+, required method not exists and method getDeclaredMethod returns exception NoSuchMethodException . 无论如何,在新的AppCompat21 +中,所需的方法不存在,方法getDeclaredMethod返回异常NoSuchMethodException

So workaround for me (tested and working on 4.x, 5.x devices) is based on direct change background parameter. 所以我的解决方法(测试和使用4.x,5.x设备)基于直接更改背景参数。 So just place this code into your Activity class. 所以只需将此代码放入Activity类中即可。

@Override
public boolean onMenuOpened(int featureId, Menu menu) {
    // enable visible icons in action bar
    if (featureId == Window.FEATURE_ACTION_BAR && menu != null) {
        if (menu.getClass().getSimpleName().equals("MenuBuilder")) {
            try {
                Field field = menu.getClass().
                        getDeclaredField("mOptionalIconsVisible");
                field.setAccessible(true);
                field.setBoolean(menu, true);
            } catch (IllegalAccessException | NoSuchFieldException e) {
                Logger.w(TAG, "onMenuOpened(" + featureId + ", " + menu + ")", e);
            }
        }
    }
    return super.onMenuOpened(featureId, menu);
}

The answer by @Simon really works well... but of you are using AppCompat Activity... you will need to use this code instead...Because onMenuOpened() is not called any more in appcompat-v7:22.x @Simon的答案确实很有效......但是你正在使用AppCompat Activity ...你需要使用这个代码...因为在appcompat-v7中不再调用onMenuOpened():22.x

@Override
    protected boolean onPrepareOptionsPanel(View view, Menu menu) {
        if(menu != null){
            if(menu.getClass().getSimpleName().equals("MenuBuilder")){
                try{
                    Method m = menu.getClass().getDeclaredMethod(
                            "setOptionalIconsVisible", Boolean.TYPE);
                    m.setAccessible(true);
                    m.invoke(menu, true);
                }
                catch(NoSuchMethodException e){
                    Log.e(Constants.DEBUG_LOG, "onMenuOpened", e);
                }
                catch(Exception e){
                    throw new RuntimeException(e);
                }
            }
        }
        return super.onPrepareOptionsPanel(view, menu);
    }

My simple mod to Simon's excellent solution to use with ActionMode: 我对Simon使用ActionMode的出色解决方案的简单模式:

 @Override
    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
        if(menu != null){
            if(menu.getClass().getSimpleName().equals("MenuBuilder")){
                try{
                    Method m = menu.getClass().getDeclaredMethod(
                            "setOptionalIconsVisible", Boolean.TYPE);
                    m.setAccessible(true);
                    m.invoke(menu, true);
                }
                catch(NoSuchMethodException e){
                    Log.e(TAG, "onPrepareActionMode", e);
                }
                catch(Exception e){
                    throw new RuntimeException(e);
                }
            }
        }
        return true;
    }

According to me this is only possible by creating a custom toolbar. 据我说,这只能通过创建自定义工具栏来实现。 Because default ActionBar doesn't gives you that feature. 因为默认的ActionBar没有为您提供该功能。 But you can put icons by taking sub menu as a child of an item. 但是你可以通过将子菜单作为项目的子项来放置图标。 And if you have better solution than me.. just inform me. 如果你有比我更好的解决方案..请告诉我。

<?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/action_settings"
    android:icon="@drawable/ic_menu_camera"
    android:showAsAction="never"
    android:title="@string/action_settings" />

<item
    android:id="@+id/action_1"
    android:icon="@drawable/ic_menu_gallery"
    android:showAsAction="never"
    android:title="Hello" />

<item
    android:id="@+id/action_search"
    android:icon="@android:drawable/ic_search_category_default"
    android:showAsAction="never"
    android:title="action_search">

    <menu>
        <item
            android:id="@+id/version1"
            android:icon="@android:drawable/ic_dialog_alert"
            android:showAsAction="never"
            android:title="Cup cake" />

        <item
            android:id="@+id/version2"
            android:icon="@drawable/ic_menu_camera"
            android:showAsAction="never"
            android:title="Donut" />


        <item
            android:id="@+id/version3"
            android:icon="@drawable/ic_menu_send"
            android:showAsAction="never"
            android:title="Eclair" />

        <item
            android:id="@+id/version4"
            android:icon="@drawable/ic_menu_gallery"
            android:showAsAction="never"
            android:title="Froyo" />
    </menu>
</item>
</menu> 

Easiest Way I found is this : 我找到的最简单方法是这样的:

public boolean onCreateOptionsMenu(Menu menu){
     MenuInflater inflater = getMenuInflater();
     inflater.inflate(R.menu.toolbar_menu,menu);
     if(menu instanceof MenuBuilder) {  //To display icon on overflow menu

          MenuBuilder m = (MenuBuilder) menu; 
          m.setOptionalIconsVisible(true);

     }
   return true;
}        `

Add this in style: 添加样式:

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/action_settings"
        app:showAsAction="always"
        android:icon="@drawable/ic_more_vert_white"
        android:orderInCategory="100"
        android:title="">
        <menu>

            <item
                android:id="@+id/Login"
                android:icon="@drawable/ic_menu_user_icon"
                android:showAsAction="collapseActionView|withText"
                android:title="@string/str_Login" />

            <item
                android:id="@+id/str_WishList"
                android:icon="@drawable/ic_menu_wish_list_icon"
                android:showAsAction="collapseActionView"
                android:title="@string/str_WishList" />

            <item
                android:id="@+id/TrackOrder"
                android:icon="@drawable/ic_menu_my_order_icon"
                android:showAsAction="collapseActionView"
                android:title="@string/str_TrackOrder" />

            <item
                android:id="@+id/Ratetheapp"
                android:icon="@drawable/ic_menu_rate_the_apps"
                android:showAsAction="collapseActionView"
                android:title="@string/str_Ratetheapp" />

            <item
                android:id="@+id/Sharetheapp"
                android:icon="@drawable/ic_menu_shar_the_apps"
                android:showAsAction="collapseActionView"
                android:title="@string/str_Sharetheapp" />

            <item
                android:id="@+id/Contactus"
                android:icon="@drawable/ic_menu_contact"
                android:showAsAction="collapseActionView"
                android:title="@string/str_Contactus" />

            <item
                android:id="@+id/Policies"
                android:icon="@drawable/ic_menu_policy_icon"
                android:showAsAction="collapseActionView"
                android:title="@string/str_Policies" />
        </menu>
    </item>
</menu>

This is too late but some one may help my try i got help from @Desmond Lua answer that helps for who uses menu.xml 这太晚了但是有些人可能会帮助我尝试从@Desmond Lua得到帮助,这有助于谁使用menu.xml

My answer is for dynamic menu creation here is my code: 我的答案是动态菜单创建这里是我的代码:

  int ACTION_MENU_ID =1;
  SpannableStringBuilder builder;
   @Override
  public boolean onCreateOptionsMenu(Menu menu) {

  //this space for icon 
    builder = new SpannableStringBuilder("  " + getString(R.string.your_menu_title));
    builder.setSpan(new ImageSpan(this,  R.drawable.ic_your_menu_icon), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
  //dynamic menu added 
    menu.add(Menu.NONE,ACTION_MENU_ID, Menu.NONE,
             getString(R.string.your_menu_title))
            .setShowAsAction(MenuItemCompat.SHOW_AS_ACTION_WITH_TEXT | MenuItemCompat.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
  //set icon in overflow menu      
        menu.findItem(ACTION_MENU_ID).setTitle(builder);
}
 public void showContextMenuIconVisible(Menu menu){
    if (menu.getClass().getSimpleName().equals("MenuBuilder")) {
        try {
            Field field = menu.getClass().getDeclaredField("mOptionalIconsVisible");
            field.setAccessible(true);
            field.setBoolean(menu, true);
        } catch (Exception ignored) {
            ignored.printStackTrace();
        }
    }
}

I used MashukKhan's suggestion but I showed the holder item as action always and used the vertical more dots from the vector assets as the icon. 我使用了MashukKhan的建议,但我始终将持有者项目显示为动作,并使用矢量资产中的垂直更多点作为图标。

<item
    android:orderInCategory="10"
    android:title=""
    android:icon="@drawable/ic_more_vert"
    app:showAsAction="always" >

    <menu>
        <item
            android:id="@+id/action_tst1"
            ...and so on

   </menu>
</item>

This produces the "overflow" menu effect and displays the icons in the drop down. 这会产生“溢出”菜单效果并在下拉列表中显示图标。
One can even put items ahead of it if they don't conflict with it showing. 如果它们与它显示不冲突,甚至可以把物品放在它前面。
I find MashukKhan's solution elegant and it fits in the solution rather than the work around category because it is just an implementation of a sub menu. 我发现MashukKhan的解决方案很优雅,它适合解决方案,而不是类别的工作,因为它只是一个子菜单的实现。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在ActionBar溢出菜单中显示图标? - How to show icons in ActionBar overflow menu? 如何使ActionBar项目显示为图标,而不显示在溢出菜单中? - How do I get my ActionBar Items to show as icons, and not in the overflow menu? 如何在actionBar菜单中强制显示图标 - How to force show icons in actionBar menu 操作栏将菜单图标显示为溢出,而不是单个图标 - Actionbar is showing menu icons as overflow and not individual icons ActionBar菜单图标仅显示在溢出菜单上 - ActionBar Menu icons only shows on overflow menu 操作栏溢出菜单项图标填充 - actionbar overflow menu items icons padding 仅当可以在ActionBar上显示文本时,才显示溢出菜单 - How to show overflow menu only if text can be displayed on the ActionBar ActionBar:“向上”图标和“溢出”菜单图标未出现,但可以使用 - ActionBar: Up icon and Overflow menu icons not appearing, but working 在上下文操作栏中的“溢出”菜单中显示图标 - Show icons in Overflow Menu in Contextual Action Bar 即使手机具有硬件菜单按钮,如何始终显示溢出菜单(ActionBar)? - How to always show overflow menu (ActionBar) even if phone has hardware menu button?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM