How can I change the Options menu background for Android 2.3?

前端 未结 6 968
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-15 11:18

I have the same standard options menu, but I want to change the background of the items from white to black. I\'ve seen many postings about how to do it, but those don\'t wo

6条回答
  •  眼角桃花
    2020-12-15 11:25

    i have used the code as shown below on 2.3.1 version and it works and just call in onCreat method addOptionsMenuHackerInflaterFactory();

    private static final int COLOR_MENU_ID = Menu.FIRST;
    private static final int EMBOSS_MENU_ID = Menu.FIRST + 1;
    private static final int BLUR_MENU_ID = Menu.FIRST + 2;
    
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
    
        menu.add(0, COLOR_MENU_ID, 0, "Color").setShortcut('3', 'c');
        menu.add(0, EMBOSS_MENU_ID, 0, "Emboss").setShortcut('4', 's');
        menu.add(0, BLUR_MENU_ID, 0, "Blur").setShortcut('5', 'z');
        return true;
    }
    
    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        super.onPrepareOptionsMenu(menu);
        return true;
    }
    
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
    
        return super.onOptionsItemSelected(item);
    }
    @SuppressWarnings("rawtypes")
    static Class       IconMenuItemView_class = null;
    @SuppressWarnings("rawtypes")
    static Constructor IconMenuItemView_constructor = null;
    
    // standard signature of constructor expected by inflater of all View classes
    @SuppressWarnings("rawtypes")
    private static final Class[] standard_inflater_constructor_signature = 
    new Class[] { Context.class, AttributeSet.class };
    
    protected void addOptionsMenuHackerInflaterFactory()
    {
        final LayoutInflater infl = getLayoutInflater();
    
        infl.setFactory(new Factory()
        {
            public View onCreateView(final String name, 
                                     final Context context,
                                     final AttributeSet attrs)
            {
                if (!name.equalsIgnoreCase("com.android.internal.view.menu.IconMenuItemView"))
                    return null; // use normal inflater
    
                View view = null;
    
                // "com.android.internal.view.menu.IconMenuItemView" 
                // - is the name of an internal Java class 
                //   - that exists in Android <= 3.2 and possibly beyond
                //   - that may or may not exist in other Android revs
                // - is the class whose instance we want to modify to set background etc.
                // - is the class we want to instantiate with the standard constructor:
                //     IconMenuItemView(context, attrs)
                // - this is what the LayoutInflater does if we return null
                // - unfortunately we cannot just call:
                //     infl.createView(name, null, attrs);
                //   here because on Android 3.2 (and possibly later):
                //   1. createView() can only be called inside inflate(),
                //      because inflate() sets the context parameter ultimately
                //      passed to the IconMenuItemView constructor's first arg,
                //      storing it in a LayoutInflater instance variable.
                //   2. we are inside inflate(),
                //   3. BUT from a different instance of LayoutInflater (not infl)
                //   4. there is no way to get access to the actual instance being used
                // - so we must do what createView() would have done for us
                //
                if (IconMenuItemView_class == null)
                {
                    try
                    {
                        IconMenuItemView_class = getClassLoader().loadClass(name);
                    }
                    catch (ClassNotFoundException e)
                    {
                        // this OS does not have IconMenuItemView - fail gracefully
                        return null; // hack failed: use normal inflater
                    }
                }
                if (IconMenuItemView_class == null)
                    return null; // hack failed: use normal inflater
    
                if (IconMenuItemView_constructor == null)
                {
                    try
                    {
                        IconMenuItemView_constructor = 
                        IconMenuItemView_class.getConstructor(standard_inflater_constructor_signature);
                    }
                    catch (SecurityException e)
                    {
                        return null; // hack failed: use normal inflater
                    }
                    catch (NoSuchMethodException e)
                    {
                        return null; // hack failed: use normal inflater
                    }
                }
                if (IconMenuItemView_constructor == null)
                    return null; // hack failed: use normal inflater
    
                try
                {
                    Object[] args = new Object[] { context, attrs };
                    view = (View)(IconMenuItemView_constructor.newInstance(args));
                }
                catch (IllegalArgumentException e)
                {
                    return null; // hack failed: use normal inflater
                }
                catch (InstantiationException e)
                {
                    return null; // hack failed: use normal inflater
                }
                catch (IllegalAccessException e)
                {
                    return null; // hack failed: use normal inflater
                }
                catch (InvocationTargetException e)
                {
                    return null; // hack failed: use normal inflater
                }
                if (null == view) // in theory handled above, but be safe... 
                    return null; // hack failed: use normal inflater
    
    
                // apply our own View settings after we get back to runloop
                // - android will overwrite almost any setting we make now
                final View v = view;
                new Handler().post(new Runnable()
                {
                    public void run()
                    {
                        v.setBackgroundColor(Color.BLUE);
    
                        try
                        {
                            // in Android <= 3.2, IconMenuItemView implemented with TextView
                            // guard against possible future change in implementation
                            TextView tv = (TextView)v;
                            tv.setTextColor(Color.RED);
                        }
                        catch (ClassCastException e)
                        {
                            // hack failed: do not set TextView attributes
                        }
                    }
                });
    
                return view;
            }
        });
    }
    

    the output for backround blue and textcolor red as shown below enter image description here

提交回复
热议问题