Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to remove icons from an ActionBarSherlock's overflow menu on Android 2.3?

I have an app with ActionBarSherlock using theme Theme.Sherlock.Light.DarkActionBar. Action bar is dark and my menu icons are light. When I run my app on small layouts, 2 or 3 menu items with icons are displayed in the overflow menu.

On Android 3+ the overflow menu items will not display their icons, but on Android 2.3 and earlier I see menu tiles with almost invisible icons, because the tile color is white and icons are close to be white.

enter image description here

As you can see, the light icons are invisible on a white background, but they must have light color to be visible on a dark action bar:

enter image description here

Can I remove icons when menu items are displayed in the overflow menu?

like image 957
Andrew Avatar asked Feb 28 '13 08:02

Andrew


3 Answers

you could use configuration qualifiers. e.g.

make a drawable folder /res/drawable-v11/ put all the "light" icons in it.

and for the darker icons use the /res/drawable/ folder.

be sure to use the same filenames in both folders.

I hope I have understood your problem and this might help you.

However, if you want to change the drawables JUST for the overflow menu, I don't think it's possible. Also because the menu icons are not intended to be used like that. ActionBarSherlock is probably also because of issues like this, not an official library.

like image 145
Aeefire Avatar answered Nov 13 '22 07:11

Aeefire


I was also facing the same issue:

there are many ways you can achieve this rather than removing image:

1)you can use respective drawable folder to put light and dark image.

2)You can also change the background color by code of your menu by checking your device version.

If you device doen't support overflow menu, the, you can change the background color of your menu as well as you can also change menu text color.

I was also facing the same issue and resolved using following one:

static final Class<?>[] constructorSignature = new Class[] {Context.class, AttributeSet.class};

class MenuColorFix implements LayoutInflater.Factory {
public View onCreateView(String name, Context context, AttributeSet attrs) {
    if (name.equalsIgnoreCase("com.android.internal.view.menu.ListMenuItemView")) {
        try {
            Class<? extends ViewGroup> clazz = context.getClassLoader().loadClass(name).asSubclass(ViewGroup.class);
            Constructor<? extends ViewGroup> constructor = clazz.getConstructor(constructorSignature);
            final ViewGroup view = constructor.newInstance(new Object[]{context,attrs});

            new Handler().post(new Runnable() {
                public void run() {
                    try {
                        view.setBackgroundColor(Color.BLACK);
                        List<View> children = getAllChildren(view);
                        for(int i = 0; i< children.size(); i++) {
                            View child = children.get(i);
                            if ( child instanceof TextView ) {
                                ((TextView)child).setTextColor(Color.WHITE);
                            }
                        }
                    }
                    catch (Exception e) {
                        Log.i(TAG, "Caught Exception!",e);
                    }

                }
            });
            return view;
        }
        catch (Exception e) {
            Log.i(TAG, "Caught Exception!",e);
        }
    }
    return null;
}       
}

public List<View> getAllChildren(ViewGroup vg) {
ArrayList<View> result = new ArrayList<View>();
for ( int i = 0; i < vg.getChildCount(); i++ ) {
    View child = vg.getChildAt(i);
    if ( child instanceof ViewGroup) {
        result.addAll(getAllChildren((ViewGroup)child));
    }
    else {
        result.add(child);
    }
}
return result;
}

@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
LayoutInflater lInflater = getLayoutInflater();
if ( lInflater.getFactory() == null ) {
    lInflater.setFactory(new MenuColorFix());
}
super.onCreateContextMenu(menu, v, menuInfo);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.myMenu, menu);
}

3) change background color from styles.xml file

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

<style name="Widget.MyTheme.ActionBar" parent="Widget.Sherlock.ActionBar">
    <item name="android:background">#ff000000</item>
    <item name="background">#ff000000</item>
</style>

For me, all of the 3 worked fine

Hope, this will work for you as well

like image 2
Akbari Dipali Avatar answered Nov 13 '22 06:11

Akbari Dipali


Another option is to remove the icons from the non-action items in onPrepareOptionsMenu.

The idea is to use actionbarsherlock's MenuItemImpl.isActionButton to figure out if each item is an action item, and if not to remove the icon. This is made a little bit tricky because onPrepareOptionsMenu is called (at least) twice by ABS - the first time when it is building the action bar, in which case MenuItemImpl.isActionButton has not yet been set and will always return false. If that's the case, you want to leave the icons alone. Once the action bar has been built the isActionButton method will return true for action bar items, false otherwise. So you want to remove the icons for the ones that return false. This is what I came up with:

@Override
public boolean onPrepareOptionsMenu(Menu menu) {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
        boolean buildingOptionsMenu = false;
        for (int i=0; i<menu.size(); ++i) {
            MenuItemImpl mi = (MenuItemImpl)menu.getItem(i);
            if (mi.isActionButton()) {
                buildingOptionsMenu = true;
                break;
            }
        }

        if (buildingOptionsMenu) {
            for (int i=0; i<menu.size(); ++i) {
                MenuItemImpl mi = (MenuItemImpl)menu.getItem(i);
                if (!mi.isActionButton()) {
                    mi.setIcon(null);
                    mi.setIcon(0);
                }
            }               
        }
    }
    return super.onPrepareOptionsMenu(menu);
}

You'll need these two imports:

import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.internal.view.menu.MenuItemImpl;

This works in ABS 4.3.0, but since it uses internal library classes it might not work with other versions of the library.

like image 1
Andy S Avatar answered Nov 13 '22 07:11

Andy S