Questo è chiaramente un problema che hanno molti programmatori e al quale Google deve ancora fornire una soluzione soddisfacente e supportata.
Ci sono molte intenzioni incrociate e incomprensioni che fluttuano intorno ai post su questo argomento, quindi leggi l'intera risposta prima di rispondere.
Di seguito includo una versione più "raffinata" e ben commentata dell'hacking da altre risposte in questa pagina, incorporando anche idee da queste domande molto strettamente correlate:
Cambia il colore di sfondo del menu Android
Come cambiare il colore di sfondo del menu delle opzioni?
Android: personalizza il menu dell'applicazione (es. Colore di sfondo)
http://www.macadamian.com/blog/post/android_-_theming_the_unthemable/
Pulsante di attivazione / disattivazione MenuItem Android
È possibile rendere lo sfondo del menu delle opzioni di Android non traslucido?
http://www.codeproject.com/KB/android/AndroidMenusMyWay.aspx
Impostare lo sfondo del menu in modo che sia opaco
Ho testato questo hack su 2.1 (simulatore), 2.2 (2 dispositivi reali) e 2.3 (2 dispositivi reali). Non ho ancora nessun tablet 3.X su cui testare, ma pubblicherò qui le modifiche necessarie quando / se lo farò. Dato che i tablet 3.X utilizzano le barre delle azioni invece dei menu delle opzioni, come spiegato qui:
http://developer.android.com/guide/topics/ui/menus.html#options-menu
questo hack quasi certamente non farà nulla (né dannoso né buono) sui tablet 3.X.
DICHIARAZIONE DEL PROBLEMA (leggere questo prima di attivare la risposta con un commento negativo):
Il menu Opzioni ha stili molto diversi su dispositivi diversi. Nero puro con testo bianco su alcuni, bianco puro con testo nero su alcuni. Io e molti altri sviluppatori desideriamo controllare il colore di sfondo delle celle del menu Opzioni così come il colore del testo del menu Opzioni .
Alcuni sviluppatori di app devono solo impostare il colore di sfondo della cella (non il colore del testo) e possono farlo in modo più pulito usando lo stile android: panelFullBackground descritto in un'altra risposta. Tuttavia, attualmente non esiste alcun modo per controllare il colore del testo del menu Opzioni con gli stili, quindi è possibile utilizzare questo metodo solo per modificare lo sfondo con un altro colore che non faccia "sparire" il testo.
Ci piacerebbe farlo con una soluzione documentata ea prova di futuro, ma semplicemente non è disponibile a partire da Android <= 2.3. Quindi dobbiamo utilizzare una soluzione che funzioni nelle versioni attuali ed è progettata per ridurre al minimo le possibilità di crash / interruzione nelle versioni future. Vogliamo una soluzione che non riesca con garbo al comportamento predefinito se deve fallire.
Ci sono molte ragioni legittime per cui potrebbe essere necessario controllare l'aspetto dei menu Opzioni (in genere per abbinare uno stile visivo per il resto dell'app), quindi non mi soffermerò su questo.
È stato pubblicato un bug di Google Android su questo: aggiungi il tuo supporto includendo questo bug (nota che Google scoraggia i commenti "anche io": basta una stella):
http://code.google.com/p/android/issues/detail?id=4441
RIEPILOGO DELLE SOLUZIONI FINORA:
Diversi poster hanno suggerito un hack che coinvolge LayoutInflater.Factory. L'hack suggerito ha funzionato per Android <= 2.2 e non è riuscito per Android 2.3 perché l'hack ha fatto un'ipotesi non documentata: che si potesse chiamare LayoutInflater.getView () direttamente senza essere attualmente all'interno di una chiamata a LayoutInflater.inflate () sulla stessa istanza LayoutInflater. Il nuovo codice in Android 2.3 ha infranto questa ipotesi e ha portato a una NullPointerException.
Il mio trucco leggermente raffinato di seguito non si basa su questo presupposto.
Inoltre, gli hack si basano anche sull'utilizzo di un nome di classe interno non documentato "com.android.internal.view.menu.IconMenuItemView" come stringa (non come tipo Java). Non vedo alcun modo per evitarlo e raggiungere l'obiettivo dichiarato. Tuttavia, è possibile eseguire l'hacking in modo accurato che ricadrà se "com.android.internal.view.menu.IconMenuItemView" non appare sul sistema corrente.
Ancora una volta, capisci che questo è un trucco e non sto affatto affermando che funzionerà su tutte le piattaforme. Ma noi sviluppatori non viviamo in un mondo accademico fantasy in cui tutto deve essere conforme alle regole: abbiamo un problema da risolvere e dobbiamo risolverlo nel miglior modo possibile. Ad esempio, sembra improbabile che "com.android.internal.view.menu.IconMenuItemView" esisterà sui tablet 3.X poiché utilizzano le barre delle azioni anziché i menu delle opzioni.
Infine, alcuni sviluppatori hanno risolto questo problema sopprimendo completamente il menu delle opzioni di Android e scrivendo la propria classe di menu (vedere alcuni dei collegamenti sopra). Non l'ho provato, ma se hai tempo per scrivere la tua vista e capire come sostituire la vista di Android (sono sicuro che il diavolo sia nei dettagli qui), allora potrebbe essere una bella soluzione che non ne richiede hack non documentati.
HACK:
Ecco il codice.
Per utilizzare questo codice, chiama addOptionsMenuHackerInflaterFactory () UNA VOLTA dalla tua attività suCreate () o dalla tua attività suCreateOptionsMenu (). Imposta una fabbrica predefinita che influenzerà la successiva creazione di qualsiasi menu Opzioni. Non influisce sui menu delle opzioni che sono già stati creati (gli hack precedenti utilizzavano un nome di funzione di setMenuBackground (), che è molto fuorviante poiché la funzione non imposta alcuna proprietà del menu prima di tornare).
@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;
}
});
}
Grazie per aver letto e divertiti!