Force overflow menu in ActionBarSherlock
Asked Answered
A

4

26

I want the 4.0+ overflow menu to be used on pre ICS devices (2.3 - 2.1). I'm using HoloEverywhere with ActionBarSherlock.

I tried the following solution:

ActionBarSherlock & HoloEverywhere - Forcing Overflow?

but it does not work because absForceOverflow does not exist. Was it removed in the newest version or something? I've checked the R files of both ABS and HE library projects and the field is simply not there.

My app's theme is set to @style/Holo.Theme.Sherlock.Light and that is the theme that i was trying to inherit from and add the absForceOverflow parameter set to true.

Auten answered 1/11, 2012 at 14:51 Comment(0)
A
19

If you are using Version 4.2.0, then .ForceOverflow themes have in fact been removed.

Source: Version 4.2.0 Changelog

Extract of the Change Log:

Add SearchView widget for standard search interaction (API 8+ only)
Fix: ShareActionProvider in the split action bar no longer fills the entire screen.
Fix: ShareActionProvider now does file I/O on a background thread.
Fix: Automatically correct ColorDrawable not respecting bounds when used as a stacked background.
Fix: Ensure fragments collection is present before dispatching events.
Fix: XML-defined onClick searches the correct context for the declared method.
Fix: Ensure action mode start/finish callbacks are invoked on the activity for the native action bar.
Fix: Allow tab callbacks to have a fragment transaction instance for any FragmentActivity.
Fix: Ensure CollapsibleActionView callbacks are dispatched in both native and compatbility action bars.
Fix: Remove .ForceOverflow themes. These never should have been included.

If you absolutely need to force Overflow, you will need to download an earlier version of ABS. You can get a list of download as per their release history here: http://actionbarsherlock.com/download.html

I personally still use the ABS version 4.1.0 since I do not currently want to make ancillary changes in my app. I also use this in my theme.xml:

<style name="MyTheme" parent="@style/Theme.Sherlock.ForceOverflow">
    <item name="android:windowBackground">@color/background</item>
    <item name="actionBarStyle">@style/Widget.Styled.ActionBar</item>
    <item name="android:actionBarStyle">@style/Widget.Styled.ActionBar</item>
</style>

<style name="MyTheme.ForceOverflow">
    <item name="absForceOverflow">true</item>
</style>

And while applying a theme for an Activity in the manifest.xml, I use this as the attribute: "@style/Theme.SociallyYOU"

Again, if you must absolutely force overflow, you might also want to read CommonsWare's thought on the same in another question here: https://mcmap.net/q/535540/-how-to-control-use-of-overflow-menu-in-ics.

NOTE: That being said, it is always better to use the latest version if the trade offs aren't to critical. By posting how I force the overflow menu, I am neither suggesting that you use an older version nor do I recommend that. It is merely informing you of the possibilities.

Altarpiece answered 1/11, 2012 at 15:28 Comment(3)
Great answer. Thank you so much! I wanted to force the overflow menu on pre ICS devices because i found that some of my users did not know that you can press the MENU button and your phone to access some of the options. I'll have to use an older version then or come up with a better solution.Auten
@Paul: Glad to have been of help. But do consider the changes made to ABS before deciding.Altarpiece
@Auten I've elaborated on this in my answer below. You can provide an alternative menu of your own if you feel it is important.Gnomon
T
36

Beginning from ActionbarSherlock 4.2 we've lost the ability to manage overflow menu visibility. To make it working, you need combine 2 approaches:

  1. To force menu visibility for Android 3.x (honeycomb) and upper, you need use this hack + add check Android version:

    public static final int DEVICE_VERSION   = Build.VERSION.SDK_INT;
    public static final int DEVICE_HONEYCOMB = Build.VERSION_CODES.HONEYCOMB;
    if (DEVICE_VERSION >= DEVICE_HONEYCOMB)
        // Code from answer above
    
  2. Open menu for pre-honeycomb devices:

    • Open ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuPresenter.java, go to method reserveOverflow
    • Replace the original with:

      public static boolean reserveOverflow(Context context) { return true; }

    This will force menu showing ...

    • but when click on menu button menu popup not showing. To achieve this we need override this in your activity class:

      @Override
      public boolean onKeyUp(int keyCode, KeyEvent event) {
          if (DEVICE_VERSION < DEVICE_HONEYCOMB) {
              if (event.getAction() == KeyEvent.ACTION_UP &&
                  keyCode == KeyEvent.KEYCODE_MENU) {
                  openOptionsMenu();
                  return true;
              }
          }
          return super.onKeyUp(keyCode, event);
      }
      

After this actions you should have absolutely working overflow action bar menu for all Android versions.

Tarrsus answered 26/11, 2012 at 15:33 Comment(5)
Thanks for the great tip! But i have to ask that how to use onKeyUp inside a Fragment, i want to handle the hardware menu key clicks.Irons
Fragment does not have key handlers, so you need to use well-known approaches to resend key event from Activity to your Fragment. I'd suggest you to create "CustomListener" in Activity and subscribe on it in the Fragment. Then trigger it in Activity's onKeyUp event: listener.onKeyUp(...).Tarrsus
+1 By far the best solution, especially better than using an old version of ActionBarSherlock that has the ForceOverflow theme.Aliciaalick
@MarcoW.: I suppose you are referring to my answer. What you failed to perhaps notice is, I am not suggesting the OP use an older version (There is a note at the end of my answer). I merely gave a solution of what needs to be done if he chooses to use an older version. To each his own anyway. ;-)Altarpiece
@IceMAN: Exactly, I did notice this. I know you weren't recommending to use an older version, but your solution is for older versions. I just wanted to express that this solution here, which does not require you to use an older version of ABS, is more future-proof, which is a fact.Aliciaalick
G
27

As Siddharth Lele has pointed out, it has been removed in the last ABS version in order to behave the same as the actual Action Bar. So at a first glance giving up on showing this menu is the best option.

However, the overflow menu showing in screen for some devices and not showing for others is a big design flaw in Android's Action Bar in my opinion. Here's why:

In devices with a hardware menu key, the menu won't show in the action bar. The tendency in most recent devices is to reduce the number of HW buttons to the minimum, since it is considered more user-friendly (and because iphones don't have but a button, so they copy this design). Other manufacturers do include the menu button but it's hidden unless you press over it (yes, it lights up when you no longer need the light. Not a wise design but again, when all the buttons are off the phone looks more iphonish).

To better understand the implications of this, let's see an example: User A has a device with menu key. He's using his favourite mail client. The options to configure mail accounts are placed in the overflow menu, along with the usual options(help, about, etc). He would like to add a second account but he doesn't have a clue on how to get to this menu. There's no info on screen to help him realize what to do. So user A asks his friend B, who is also using this mail client. User B has the latest Nexus N+1 Googlephone, and he's able to view the overflow icon in the action bar because his device doesn't sport a HW menu key. He shows A how he can add a 2nd account by opening this menu. User A is now totally confused, since they are using the same app versions. Frustated, A might think the problem is in his phone for being too old. B is also confused as well.

At this point you might be thinking both A and B are fools who can't figure how to use an smartphone. But unlike desktop apps, a great majority of smartphone users don't know but the basics about their devices. Their previous phone might well have been a keypad device with a simple firmware. The battery died and they went to the store for a replace, but it was out of stock. They could have ordered one in the internet but it was more expensive than buying a newer phone. So they were sold a touchscreen-enabled phone because that's how phones are nowadays. Now they have to face an small computer with a full-fledged OS. To make things worse, the phone comes only with a "quick start guide", and to get the full manual they have to download a pdf from the internet. Guess what? They won't.

If you are developing a mobile app you should assume the user might not know a thing about computers, the OS, or similar apps. You should make the GUI look similar across devices, so that people can learn and remember how to use it. Don't blame on Action Bar designers: if users like A or B don't know how to go to the options menu it's your fault in the first place. That's why you should have included a means of getting to options screen always visible.

Something similar happens with the back key. Some devices might have a HW back key, newer ones usually don't. But whenever we can go back in our apps we're always displaying that arrow-like button in the Action Bar, right? And yes, I know one button navigates back in the "navigation tree" while the other goes "back in time", but this is also another design flaw: for the mean user, back is just back. He has this button in the screen and he can also use the HW one, but this is optional. The same should have been done with the overflow menu.

So if you think (like me) that this is an important button, don't give up. Provide a regular main options menu and populate it with the pertinent submenus. Make it an action button and assign it a descriptive icon, or even a textual description like "MENU". You can also mimic the overflow menu icon, just use one of these drawables:

    // For ActionBarSherlock
    abs__ic_menu_moreoverflow_normal_holo_dark.png
    abs__ic_menu_moreoverflow_normal_holo_light.png

    // For ActionBar
    ic_menu_moreoverflow_normal_holo_light.png
    ic_menu_moreoverflow_normal_holo_dark.png

Moreover: go and copy-paste the images to your project res folder. You can never know whether future releases of ABS or the next implementation of ActionBar will include them.

Gnomon answered 12/11, 2012 at 9:49 Comment(8)
Interesting. You're not only answering technically but also mentioning a UX principle. I got inspired, thanks.Spier
@Evi Song I'm surprised someone took the time to read such a large answer. Thanks to you for reading!Gnomon
Your comment should be the reason enough to put the .ForceOverflow in the library again! Thanks for your clear view and I totally agree with it.Tayib
@Tayib You're welcome. But I think Jake Wharton was right in removing that option. ABS should mimic as close as possible the actual Action Bar.Gnomon
I agree, but I think not adding the overflow item when there is a hardware button present is confusing, I sometimes really miss the pop-up ability and after searching and thinking I suddenly realize I have a hardware popup button :)Tayib
This is perfect idea, but is there any way to know how many items are appearings in actionbar so adding ... item should be at the end.Damara
Even now twitter new app use this hack so its been benchmark ;)Shingles
The simplest method. But then it will be a slight hassle to merge menu items from 2 XML resources, right? Or there is a shortcut to merge sub-items?Sawdust
A
19

If you are using Version 4.2.0, then .ForceOverflow themes have in fact been removed.

Source: Version 4.2.0 Changelog

Extract of the Change Log:

Add SearchView widget for standard search interaction (API 8+ only)
Fix: ShareActionProvider in the split action bar no longer fills the entire screen.
Fix: ShareActionProvider now does file I/O on a background thread.
Fix: Automatically correct ColorDrawable not respecting bounds when used as a stacked background.
Fix: Ensure fragments collection is present before dispatching events.
Fix: XML-defined onClick searches the correct context for the declared method.
Fix: Ensure action mode start/finish callbacks are invoked on the activity for the native action bar.
Fix: Allow tab callbacks to have a fragment transaction instance for any FragmentActivity.
Fix: Ensure CollapsibleActionView callbacks are dispatched in both native and compatbility action bars.
Fix: Remove .ForceOverflow themes. These never should have been included.

If you absolutely need to force Overflow, you will need to download an earlier version of ABS. You can get a list of download as per their release history here: http://actionbarsherlock.com/download.html

I personally still use the ABS version 4.1.0 since I do not currently want to make ancillary changes in my app. I also use this in my theme.xml:

<style name="MyTheme" parent="@style/Theme.Sherlock.ForceOverflow">
    <item name="android:windowBackground">@color/background</item>
    <item name="actionBarStyle">@style/Widget.Styled.ActionBar</item>
    <item name="android:actionBarStyle">@style/Widget.Styled.ActionBar</item>
</style>

<style name="MyTheme.ForceOverflow">
    <item name="absForceOverflow">true</item>
</style>

And while applying a theme for an Activity in the manifest.xml, I use this as the attribute: "@style/Theme.SociallyYOU"

Again, if you must absolutely force overflow, you might also want to read CommonsWare's thought on the same in another question here: https://mcmap.net/q/535540/-how-to-control-use-of-overflow-menu-in-ics.

NOTE: That being said, it is always better to use the latest version if the trade offs aren't to critical. By posting how I force the overflow menu, I am neither suggesting that you use an older version nor do I recommend that. It is merely informing you of the possibilities.

Altarpiece answered 1/11, 2012 at 15:28 Comment(3)
Great answer. Thank you so much! I wanted to force the overflow menu on pre ICS devices because i found that some of my users did not know that you can press the MENU button and your phone to access some of the options. I'll have to use an older version then or come up with a better solution.Auten
@Paul: Glad to have been of help. But do consider the changes made to ABS before deciding.Altarpiece
@Auten I've elaborated on this in my answer below. You can provide an alternative menu of your own if you feel it is important.Gnomon
R
0

I find Exterminator13’s answer doesn't work on some kind of Android devices(The total number I think is quite small), but to fit for as much devices as possible, I uses dialog and use one menu with android:showAsAction="always" as overflow menu button.After all, the effect of overflow menu of actionbarsherlock is realized by its source, so why not realize the effect by our self if it is not so troublesome. If you understand Chinese,You can also see my blog.

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
    <item
        android:id="@+id/more"
        android:icon="@drawable/overflow"
        android:showAsAction="always" 
    />
</menu>

 

private Dialog popupDialog;
private Boolean popupState=false;

    public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case android.R.id.home:
        this.finish();
        return true;
    case R.id.more:
        if (!popupState) {
            showPop();
        }else {
            popupDialog.dismiss();
        }
    default:
        return super.onOptionsItemSelected(item);
    }
}

private void showPop(){
    LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View view = inflater.inflate(ResID, null);
    ListView listView = (ListView) view.findViewById(ResID);
    listView.setAdapter(yourOwnAdapter);
    popupDialog = new Dialog(WifiAuthWireActivity.this);
    popupDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
    popupDialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.WHITE));
    popupDialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
    popupDialog.setContentView(view);
    // Calculate ActionBar height
    TypedValue tv = new TypedValue();
    ActionBar maActionBar=getSupportActionBar();
    int actionBarHeight=maActionBar.getHeight();
    if (getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true))
    {
        actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data,getResources().getDisplayMetrics());
    }
    WindowManager.LayoutParams wmlp = popupDialog.getWindow().getAttributes();
    wmlp.gravity = Gravity.TOP | Gravity.RIGHT;
    wmlp.x+=12;
    wmlp.y+=actionBarHeight;
    popupDialog.getWindow().setAttributes(wmlp);
    popupDialog.show();
}
Robichaud answered 2/11, 2013 at 15:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.