How to show icons on overflow menu in ActionBar

I know this is not possible using my own API. Is there any way around this?

+62
android actionbarsherlock android-actionbar android-menu
Aug 22 '13 at 7:27
source share
15 answers

The previously posted answer is fine, generally speaking. But basically it eliminates the default behavior of the overflow menu. Things like the number of icons can be displayed on different screen sizes, and then they popped up in the overflow menu when they cannot be displayed. By doing the above, you remove many important features.

A better way would be to tell the overflow menu to display the icons directly. You can do this by adding the following code to your 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); } 
+84
Mar 09 '14 at 10:15
source share

In your xml menu, use the following syntax for the submenu, you will begin to receive a menu with icons

 <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> 

+53
Dec 01 '13 at 22:37
source share

Tried this based on previous answers, and it works great, at least with later versions of the support library (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; } 
+39
Feb 15 '17 at 15:32
source share

You can use 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); } 
+22
Sep 11 '15 at 12:49
source share

The answer from Simon was very useful to me, so I want to share how I implemented it in the onCreateOptionsMenu method, as suggested:

 @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 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); } 
+13
Aug 22 '15 at 16:49
source share

Based on @Desmond Lua's answer from above , I made a static method for using drawable declared in XML in a drop-down list and so that its tinted color does not affect the state of Constable Drawable.

  /** * Updates a menu item in the dropdown to show it 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 will look something like this if used in action. It may 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; } 
+7
Aug 10 '16 at 18:48
source share

The best, but not made, decision probably works on older platforms. In any case, in the new AppCompat21 +, the required method does not exist, and the getDeclaredMethod method returns a NoSuchMethodException .

So, the workaround for me (tested and working on 4.x, 5.x devices) is based on the direct change background parameter. So just put this code in your Activity class.

 @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); } 
+3
Feb 15 '15 at 10:32
source share

@Simon's answer really works well ... but you are using AppCompat Activity ... you will need to use this code ... because onMenuOpened () is no longer called in appcompat-v7: 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); } 
+3
May 25 '16 at 19:24
source share

My simple mod for Simon is a great solution for use with 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; } 
+2
Oct 11 '15 at 22:35
source share

In my opinion, this is only possible when creating a custom toolbar. Since ActionBar does not give you this function by default. But you can put icons by selecting a submenu as a child. And if you have a better solution than me, just let me know.

 <?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> 
+2
Sep 14 '16 at 12:53 on
source share

The easiest way I've 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; } ' 
+2
Oct 04 '18 at 10:44 on
source share

Add this to the 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> 
+1
Dec 20 '15 at 16:39
source share

It's too late, but someone can help in my attempt to get help from @Desmond Lua which helps those using menu.xml

My answer for creating a dynamic menu 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); } 
+1
Mar 08 '16 at 8:09
source share
  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(); } } } 
0
Aug 23 '17 at 12:54 on
source share

I used the MashukKhan sentence, but always showed the holder element as an action and used the vertical icon more dots from vector assets as an icon.

 <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 creates the effect of the Overflow menu and displays the icons in the drop-down list.
You can even put elements in front of him, if they do not conflict with him, showing.
I find the MashukKhan solution elegant, and it fits into the solution, not the workaround category, because it's just an implementation of a submenu.

0
Sep 07 '19 at 1:48
source share



All Articles