showAsAction="ifRoom" doesn't show the item even when there is plenty of room

AndroidAndroid LayoutAndroid ActionbarActionbarsherlockAndroid Menu

Android Problem Overview


I am trying to get the ActionBar working properly on my app (and I'm using ActionBarSherlock to get a unified UI between Android 2.x and 4.x).

I feel like android:showAsAction="ifRoom" is just a big, fat lie. Whenever I set an action to ifRoom it ALWAYS shows up in the overflow menu even if there is PLENTY of room. Here are two screenshots from the same emulator. The first shows the ActionBar with all options set to always and the second shows the ActionBar with the last two options set to ifRoom. As you can see, there was PLENTY of room when they were all shown in the always screenshot, so why aren't they all showing in the second because they DO have room?

enter image description here

enter image description here

Here is my menu.xml:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >

    <item
        android:id="@+id/add"
        android:icon="@drawable/ic_menu_btn_add"
        android:showAsAction="always"
        android:title="Add"/>
    <item
        android:id="@+id/calculateNPV"
        android:icon="@drawable/menu_icon_npv"
        android:showAsAction="always"
        android:title="NPV"/>
    <item
        android:id="@+id/calculateIRR"
        android:icon="@drawable/menu_icon_irr"
        android:showAsAction="always"
        android:title="IRR/YR"/>
    <item
        android:id="@+id/send"
        android:icon="@android:drawable/ic_menu_share"
        android:showAsAction="always"
        android:title="@string/share_pdf"/>
    <item
        android:id="@+id/graph"
        android:icon="@drawable/ic_menu_gallery"
        android:showAsAction="ifRoom"
        android:title="@string/view_cashflow_diagram"/>
    <item
        android:id="@+id/deleteReorder"
        android:icon="@drawable/ic_menu_clear_playlist"
        android:showAsAction="ifRoom"
        android:title="@string/delete_reorder_cashflows"/>

</menu>

Android Solutions


Solution 1 - Android

I hope I am not too late in coming to the party.

It is really not a big fat lie but a small oversight.

The showAsAction attribute must be defined using a different namespace "http://schemas.android.com/apk/res-auto"

You should therefore in your top menu tag define a namespace as follows xmlns:app="http://schemas.android.com/apk/res-auto"

and then use that to define your showAsAction attribute like so app:showAsAction="ifRoom"

That should fix it

Solution 2 - Android

It's because there is specified maximum number of items that should go to actionbar and it seems to be 4. Of course you can force them to appear by setting showAsAction: always but regarding to google API guides:

> If you believe that more than four of your menu items can be justified > as action items, then you should carefully consider their relative > level of importance and try to set no more than four as action items > (and do so using the "ifRoom" value to allow the system to put some > back in the overflow menu when space is limited on smaller screens). > Even if space is available on a wide screen, you should not create a > long stream of action items that clutter the UI and appear like a > desktop toolbar, so keep the number of action items to a minimum. > > Additionally, the following actions should never appear as action > items: Settings, Help, Feedback, or similar. Always keep them in the > overflow menu.

Solution 3 - Android

To complement the answer from Michal Z.: The Android Design Guide Page Patterns->Actionbar says the following in the chapter "Action Buttons":

http://developer.android.com/design/patterns/actionbar.html

How many actions will fit in the main action bar? Action bar capacity is controlled by the following rules:

  • Action buttons in the main action bar may not occupy more than 50% of the bar's width.
  • Action buttons on bottom action bars can use the entire width.
  • The screen width in density-independent pixels (dp) determine the number of items that will fit in the main action bar:
    • smaller than 360 dp = 2 icons
    • 360-499 dp = 3 icons
    • 500-599 dp = 4 icons
    • 600 dp and larger = 5 icons

Solution 4 - Android

use app:showAsAction="always" instead of android:showAsAction="always"

Solution 5 - Android

Use

<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:yourapp="http://schemas.android.com/apk/res-auto" >

Solution 6 - Android

ActivityBar strives not to exceed some amount of visible elements. And that limit is lower than ActivityBar can contain indeed. The limit is set in android.support.v7.view.ActionBarPolicy class:

`/**
* Returns the maximum number of action buttons that should be permitted within an action
* bar/action mode. This will be used to determine how many showAsAction="ifRoom" items can fit.
* "always" items can override this.
*/
public int getMaxActionButtons() {
final Resources res = mContext.getResources();
final int widthDp = ConfigurationHelper.getScreenWidthDp(res);
final int heightDp = ConfigurationHelper.getScreenHeightDp(res);
final int smallest = ConfigurationHelper.getSmallestScreenWidthDp(res);



    if (smallest > 600 || widthDp > 600 || (widthDp > 960 && heightDp > 720)
            || (widthDp > 720 && heightDp > 960)) {
        // For values-w600dp, values-sw600dp and values-xlarge.
        return 5;
    } else if (widthDp >= 500 || (widthDp > 640 && heightDp > 480)
            || (widthDp > 480 && heightDp > 640)) {
        // For values-w500dp and values-large.
        return 4;
    } else if (widthDp >= 360) {
        // For values-w360dp.
        return 3;
    } else {
        return 2;
    }
}`




As you can see the limit is between 2 and 5, and it depends on the screen width.




I haven't been able to find a way to change this behavior. So if you want to exceed the limit, you should use showAsAction="always" or create your own view for ActionBar.


Solution 7 - Android

Use this below code it will always work

<menu 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools" 
    tools:context=".MainActivity">
    <item 
        android:id="@+id/menu_share" 
        android:title="Share"
        android:orderInCategory="100" 
        app:showAsAction="ifRoom"
        android:actionProviderClass="android.widget.ShareActionProvider"/>
</menu>

Solution 8 - Android

Android will show at most 5 buttons, including the menu, indeed, but you can override that behavior if you want.

Keep in mind that the Material design guideline is to have a limited number of buttons on the toolbar. And keep in mind some actions should never be be displayed as buttons even if there's room.

But if you have a few specific actions that make sense, you can show them even if you will have more than 5 in total. You only have to check the screen width yourself.

First, in the menu definition, use "always" for up to 4 buttons you want to have displayed at all times. Use "never" for all the others, including those you may programmatically show as icons.

Then, override onPrepareOptionsMenu to add logic to force display a few more actions as buttons.

@Override
public boolean onPrepareOptionsMenu(Menu menu) {
    final Configuration config = getResources().getConfiguration();
    final int width = config.screenWidthDp;

    if (width > 400) {
        MenuItem item = menu.findItem(R.id.your_action);
        item.setShowAsAction(SHOW_AS_ACTION_ALWAYS);

        item = menu.findItem(R.id.another_action);
        item.setShowAsAction(SHOW_AS_ACTION_ALWAYS);
    }

    return super.onPrepareOptionsMenu(menu);
}

You can also do this dynamically, when the orientation changes, since there's usually enough room in landscape mode, especially on tablets.

    @Override
    public void onConfigurationChanged(@NonNull Configuration newConfig) {
        super.onConfigurationChanged(newConfig);

        invalidateOptionsMenu();
    }

But don't clutter the toolbar. And remember to test this on small devices.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKenny WylandView Question on Stackoverflow
Solution 1 - AndroidjosagyemangView Answer on Stackoverflow
Solution 2 - AndroidMichał Z.View Answer on Stackoverflow
Solution 3 - Androidarne.jansView Answer on Stackoverflow
Solution 4 - AndroidRahul_PawarView Answer on Stackoverflow
Solution 5 - AndroidRavi KarkiView Answer on Stackoverflow
Solution 6 - AndroidivanView Answer on Stackoverflow
Solution 7 - AndroidrajView Answer on Stackoverflow
Solution 8 - AndroidAlfred FaltiskaView Answer on Stackoverflow