50

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

10 Answers 10

43

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

6
  • 12
    I had the exact same issue - and in fact in my case - I had to do exactly opposite: use android:showAsAction namespace to fix this issue.
    – KurtCobain
    Commented Jun 13, 2014 at 17:10
  • 5
    If you are using ActionBarActivity you need to use the namespace. Using Activity you can use android:showAsAction
    – nickromano
    Commented Mar 9, 2015 at 22:54
  • 1
    I tried it, did not work for me. Android documentation does not even support it. Commented May 20, 2015 at 23:38
  • 1
    @KurtCobain Using the android namespace fixes my problem! Commented Jul 24, 2015 at 0:15
  • 1
    If you are using the appcompat library you need to use app. Otherwise you should use android. Commented Sep 5, 2016 at 20:23
15

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.

6
  • 17
    It's not always 4. See this chart: developer.android.com/design/media/action_bar_pattern_table.png Commented Apr 10, 2013 at 6:20
  • 4
    But as you can see, there IS room for those actions, so -ifRoom- is a big, fat lie. :) It's also frustrating that there is no visible indicator that there ARE more options available via the Menu button. It's much worse to show them SOME options but not all without an indicator, because showing SOME tells the user that this is the location to look. Why would there be another location? Commented Apr 10, 2013 at 6:23
  • 1
    @Jake Wharton: Yeah right! I knew that I have seen something like this before but I couldn't remember where. Now I think that it was in one of google design in action videos about ActionBar... Thanks!
    – Michał Z.
    Commented Apr 10, 2013 at 6:24
  • 1
    @Kenny Wyland: watch this youtube.com/watch?v=jes1iXRFRw0 it should explain some things. There can be other things on ActionBar than "buttons". I agree about the thing with physical menu button and that there is no indicator that there are more items.
    – Michał Z.
    Commented Apr 10, 2013 at 6:33
  • 1
    Jake Wharton: for context and rules quoted in my answer, I give the link to the relevant page from the design guide: developer.android.com/design/patterns/actionbar.html
    – arne.jans
    Commented Dec 17, 2013 at 12:52
11

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
6

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

0
1

Use

<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:yourapp="http://schemas.android.com/apk/res-auto" >
1
  • 6
    Please explain your answer, as code only answers are usually unclear and harder to understand. Commented Jun 8, 2015 at 15:42
1

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.

0

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>
1
  • Insted of use android:actionProviderClass="android.widget.ShareActionProvider"/> Use app:actionProviderClass="android.support.v7.widget.ShareActionProvider"/>
    – Quimbo
    Commented Feb 9, 2019 at 5:07
0

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.

0

It has nothing to do with AppCompatActivity or appcompat library.

just use

menuInflater.inflate(R.menu.main_menu, menu)

instead of

MenuInflater(this).inflate(R.menu.main_menu, menu)
0

just would like to add that if you write (in Android Studio) showAsAction without the prefix of app: then it will probably will added to the parent tag as josagyemang mentioned

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.