Esse é claramente um problema que muitos programadores enfrentam e para o qual o Google ainda não forneceu uma solução compatível e satisfatória.
Existem muitas intenções cruzadas e mal-entendidos flutuando em torno das postagens sobre este tópico, portanto, leia toda esta resposta antes de responder.
Abaixo, incluo uma versão mais "refinada" e bem comentada do hack de outras respostas nesta página, também incorporando ideias dessas questões intimamente relacionadas:
Alterar a cor de fundo do menu do Android
Como mudar a cor de fundo do menu de opções?
Android: personalizar o menu do aplicativo (por exemplo, cor de fundo)
http://www.macadamian.com/blog/post/android_-_theming_the_unthemable/
Botão de alternância de item de menu do Android
É possível tornar o fundo do menu de opções do Android não translúcido?
http://www.codeproject.com/KB/android/AndroidMenusMyWay.aspx
Configurando o fundo do menu para ser opaco
Testei esse hack no 2.1 (simulador), 2.2 (2 dispositivos reais) e 2.3 (2 dispositivos reais). Não tenho nenhum tablet 3.X para testar ainda, mas postarei as alterações necessárias aqui quando / se eu tiver. Dado que os tablets 3.X usam barras de ação em vez de menus de opções, conforme explicado aqui:
http://developer.android.com/guide/topics/ui/menus.html#options-menu
este hack quase certamente não fará nada (nenhum mal e nenhum bem) em tablets 3.X.
DECLARAÇÃO DO PROBLEMA (leia isto antes de disparar e responder com um comentário negativo):
O menu Opções tem estilos muito diferentes em dispositivos diferentes. Preto puro com texto branco em alguns, branco puro com texto preto em alguns. Eu e muitos outros desenvolvedores desejamos controlar a cor de fundo das células do menu Opções , bem como a cor do texto do menu Opções .
Certos desenvolvedores de aplicativos só precisam definir a cor de fundo da célula (não a cor do texto) e podem fazer isso de maneira mais limpa usando o estilo android: panelFullBackground descrito em outra resposta. No entanto, atualmente não há como controlar a cor do texto do menu Opções com estilos e, portanto, só se pode usar esse método para alterar o plano de fundo para outra cor que não fará o texto "desaparecer".
Adoraríamos fazer isso com uma solução documentada e preparada para o futuro, mas uma simplesmente não está disponível no Android <= 2.3. Portanto, temos que usar uma solução que funcione nas versões atuais e seja projetada para minimizar as chances de travar / quebrar em versões futuras. Queremos uma solução que retorne normalmente ao comportamento padrão caso tenha que falhar.
Existem muitas razões legítimas pelas quais alguém pode precisar controlar a aparência dos menus de opções (normalmente para corresponder a um estilo visual para o resto do aplicativo), então não vou me alongar sobre isso.
Há um bug do Google Android postado sobre isso: por favor, adicione seu apoio marcando este bug (observe que o Google desencoraja comentários "eu também": apenas uma estrela é suficiente):
http://code.google.com/p/android/issues/detail?id=4441
RESUMO DAS SOLUÇÕES ATÉ AGORA:
Vários pôsteres sugeriram um hack envolvendo LayoutInflater.Factory. O hack sugerido funcionou para Android <= 2.2 e falhou para Android 2.3 porque o hack fez uma suposição não documentada: que alguém poderia chamar LayoutInflater.getView () diretamente sem estar atualmente em uma chamada para LayoutInflater.inflate () na mesma instância LayoutInflater. O novo código no Android 2.3 quebrou essa suposição e levou a uma NullPointerException.
Meu hack ligeiramente refinado abaixo não se baseia nessa suposição.
Além disso, os hacks também contam com o uso de um nome de classe interna não documentado "com.android.internal.view.menu.IconMenuItemView" como uma string (não como um tipo Java). Não vejo como evitar isso e ainda cumprir o objetivo declarado. No entanto, é possível fazer o hack de uma maneira cuidadosa, que retornará se "com.android.internal.view.menu.IconMenuItemView" não aparecer no sistema atual.
Mais uma vez, entenda que isso é um hack e de forma alguma estou afirmando que isso funcionará em todas as plataformas. Mas nós, desenvolvedores, não vivemos em um mundo acadêmico fantasioso, onde tudo tem que estar de acordo com as regras: temos um problema a resolver e temos que resolvê-lo da melhor maneira possível. Por exemplo, parece improvável que "com.android.internal.view.menu.IconMenuItemView" exista em tablets 3.X, pois eles usam barras de ação em vez de menus de opções.
Finalmente, alguns desenvolvedores resolveram esse problema suprimindo totalmente o menu de opções do Android e escrevendo sua própria classe de menu (veja alguns dos links acima). Eu não tentei isso, mas se você tiver tempo para escrever sua própria visão e descobrir como substituir a visão do Android (tenho certeza que o diabo está nos detalhes aqui), então pode ser uma boa solução que não requer nenhum hacks não documentados.
HACK:
Aqui está o código.
Para usar este código, chame addOptionsMenuHackerInflaterFactory () UMA VEZ de sua atividade onCreate () ou sua atividade onCreateOptionsMenu (). Ele define uma fábrica padrão que afetará a criação subsequente de qualquer Menu de Opções. Não afeta os menus de opções que já foram criados (os hacks anteriores usavam um nome de função setMenuBackground (), o que é muito enganoso, pois a função não define nenhuma propriedade do menu antes de retornar).
@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.BLACK);
try
{
// in Android <= 3.2, IconMenuItemView implemented with TextView
// guard against possible future change in implementation
TextView tv = (TextView)v;
tv.setTextColor(Color.WHITE);
}
catch (ClassCastException e)
{
// hack failed: do not set TextView attributes
}
}
});
return view;
}
});
}
Obrigado pela leitura e divirta-se!