Saturday, June 18, 2011

How to change the background color of Android options menu

I have been trying my hand at developing apps with Android.  I have had my fair share of leanings.  Today I am going to share my experience around styling the options menu in Android.

What is the options menu?

Options menu is the menu that is shown to the user when the Menu key is pressed on the Android phone.

Lets look at an example, that will make things easier to understand.

The layout file.

The above code shows the following GUI
As you can see from the above screenshot the background color of the Activity is greenish while the default Color of the selected element of the options menu is Orange.

It definitely looks inconsistent and ugly.  This is the reason we need to style the options menu to match the rest of the application theme.

Android platform is highly configurable.  One can change all aspects of look and feel on the android platform.  Hence, when this task was given to me, I thought it would be a 2 min fix.  But unfortunately it took much longer than I expected.

All I wanted to do is change the background selector of the options menu.  Android does not provide a straight forward way to do this.  In fact, it meant writing quiet some code.  I decided to write a post on this, so that other can benefit from my learning's.

So back to the original question.  How do we change the background color of Android options menu?

How do they do it?

Now there is nothing fancy about the above code.  But to change the background color we have to write some fancy code :)

Changing the options menu background color is a 8 step process
  1. Setting the custom LayoutInflater.Factory instance.
  2. Implementing the onCreateView method that will actually set the background selector for the options menu.
  3. In the implementation of onCreateView, check if the view that is to be created is of type com.android.internal.view.menu.IconMenuItemView.  Yes, I know, its an *internal* class!
  4. If the view is of type IconMenuItemView then create the view using the LayoutInflater.
  5. At this point we have an instance of IconMenuItemView but we cannot change the background color of the view directly.  Even if we change the background color at this point, framework updates it again and our changes are overwritten
  6. We have to change the background color after the view has rendered, using the Handler API.
  7. Change the background color in run method of the Runnable instance that we pass to the Handler's post method.
  8. Catch all exceptions that could occur in the entire process.  Notice that, we are using an internal class there are high changes that its behavior could change without any notice.  In fact this approach does not work on Android 2.3.  In this case we have to fallback to the default menu styling.
Yep, I know, it looks like a lot of work and pretty complex too.  Lets look at the code to make things more clear.

The menu_selector is an XML file that choses the background color based on the state of the menu item.  My menu_selector.xml looks like this

The colors.xml file looks like

The comments are embedded in the code. One new methods has been added called setMenuBackground. This method does the job for us!

The screenshots of the styled options menu
 As we can see the Options Menu background color has been changed from Orange to greenish.

That's all folks!

We have successfully changed the background color of Android options men.  But wait a minute, how to change the default text color of the Android options menu?  If this question is bothering you stay tuned, in the next post I am going to explain exactly that!

14 comments:

  1. Hi, it didn't work for me :(, i don't know why...
    Could you post the project?
    For example, in android:background="@drawable/header_background", you didn't post "header_background", so i did:
    android:background="@color/fundo_tela"
    i don't know if this is the error, i'm a begginer, so...

    My email: nissi-miranda@bol.com.br

    ReplyDelete
  2. Hello There,

    Please note that this method does not work on Android 2.3. What version of android are you using?

    What error are you getting while trying the code?

    ReplyDelete
  3. Nice work man....! can i set menu icon as well with background color????I am trying but not getting...any help????

    ReplyDelete
  4. Hello M Sheraz Amin,

    You can see the menu icon very easily. The Menu class has a method .setIcon(), which takes in a drawable resource reference.

    Thanks

    Deep Shah

    ReplyDelete
  5. Not working for me either. I'm building for 2.1. Getting an inflate exception at the < final View view = f.createView(name, null, attributeSet); > : Binary XML file line #17: Error inflating class com.android.internal.view.menu.IconMenuItemView

    ReplyDelete
  6. Same for me.. not working even though I tinkered quite a bit.


    binary option

    ReplyDelete
  7. This is just awesome. I hope this works for me because I want to change the background.
    how to unlock htc

    ReplyDelete
  8. Getting Error in "menu_selector.xml"

    these lines.....(

    android:drawable="@color/menu_pressed"/>
    android:drawable="@color/menu_focused"/>
    android:drawable="@color/menu_normal"/>

    )

    ReplyDelete
  9. it doesn't work on android 2.3

    ReplyDelete
  10. How do you change the color of the pressed state in the menu?

    ReplyDelete
  11. hello there,i'm trying to change the background color of my android screeand i don't know how to write the code and where... plz can u help me

    ReplyDelete
  12. Its does not work for me.
    The error is
    Error inflating class com.android.internal.view.menu.IconMenuItemView

    ReplyDelete
  13. Thanks it worked for me :D

    ReplyDelete
  14. How do you keep the default color Android when state_focused="true"?

    ReplyDelete

Have some Fun!