Come cambiare il colore di sfondo del menu delle opzioni?


96

Sto cercando di cambiare il colore predefinito per il menu delle opzioni che è bianco: voglio uno sfondo nero per ogni elemento nel menu delle opzioni.

Ho provato alcune foto come android: itemBackground = "# 000000" sull'elemento item all'interno dell'elemento menu ma non ha funzionato.

Come posso farlo?



Risposte:


65

Dopo aver trascorso una notevole quantità di tempo a provare tutte le opzioni, l'unico modo in cui sono stato in grado di ottenere un'app utilizzando AppCompat v7 per modificare lo sfondo del menu di overflow era utilizzare l'attributo itemBackground:

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    ...
    <item name="android:itemBackground">@color/overflow_background</item>
    ...
</style>

Testato da API 4.2 a 5.0.


2
Questa dovrebbe essere la risposta accettata, facile e semplice.
Alex Ardavin

3
Ma questo rimuove l'effetto a catena: / Comunque per rimetterlo?
David Velasquez

Voglio cambiare lo sfondo dell'intera finestra, non lo sfondo dell'elemento separato, ad esempio aggiungerà bordi a ogni elemento se imposti tale sfondo (con bordi) ...
user25

1
E il colore del testo del menu?
doctorram

51

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!


15
L'unica cosa che ho in modo affidabile quando si cerca di utilizzare questo (e soluzione simile) è `java.lang.IllegalStateException: Una fabbrica è già stato impostato su questo LayoutInflater`
Bostone

Per me va bene! Così bello avere finalmente una soluzione! Testato su Gingerbread, Honeycomb e ICS
Chad Schultz

Testato su Samsung Galaxy Nexus (4.1.1) e funzionante! Roba buona, Louis!
Felipe Caldas

2
Funziona su Galaxy Nexus 7 (4.1.1), tuttavia il colore del testo viene ripristinato per ogni successiva chiamata al menu dopo essere stato nascosto per la prima volta.
Will Kru

1
Ottengo anche l'IllegalStateException. Sembra che l'hack non sia compatibile con ActionBarSherlock, che sto usando.
Travis

20

L'attributo di stile per lo sfondo del menu è android:panelFullBackground.

Nonostante ciò che dice la documentazione, deve essere una risorsa (ad esempio @android:color/blacko @drawable/my_drawable), se si utilizza direttamente un valore di colore si verificherà un arresto anomalo.

Questo eliminerà anche i bordi degli oggetti che non sono stato in grado di modificare o rimuovere utilizzando la soluzione di primalpop.

Per quanto riguarda il colore del testo, non ho trovato alcun modo per impostarlo tramite gli stili nella 2.2 e sono sicuro di aver provato di tutto (è così che ho scoperto l'attributo di sfondo del menu). Dovresti usare la soluzione di primalpop per questo.


3
Dove devo impostare questo valore? Non sono riuscito a farlo funzionare su Android 2.2. o 2.3
Janusz

1
@ Janusz In Styles.xml. Questo probabilmente aiuterà: developer.android.com/guide/topics/resources/…
Pilot_51

2
Non funziona, bello se potessi indicare dove dovrebbe andare, provato ovunque tranne che per creare un altro stile per le mie voci di menu da attribuire .....
John

14

Per Android 2.3 questo può essere fatto con un hacking molto pesante:

La causa principale dei problemi con Android 2.3 è che in LayoutInflater mConstructorArgs [0] = mContext viene impostato solo durante l'esecuzione di chiamate a

http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.3.3_r1/android/view/LayoutInflater.java/#352

protected void setMenuBackground(){

    getLayoutInflater().setFactory( new Factory() {

        @Override
        public View onCreateView (final String name, final Context context, final AttributeSet attrs ) {

            if ( name.equalsIgnoreCase( "com.android.internal.view.menu.IconMenuItemView" ) ) {

                try { // Ask our inflater to create the view
                    final LayoutInflater f = getLayoutInflater();
                    final View[] view = new View[1]:
                    try {
                        view[0] = f.createView( name, null, attrs );
                    } catch (InflateException e) {
                        hackAndroid23(name, attrs, f, view);
                    }
                    // Kind of apply our own background
                    new Handler().post( new Runnable() {
                        public void run () {
                            view.setBackgroundResource( R.drawable.gray_gradient_background);
                        }
                    } );
                    return view;
                }
                catch ( InflateException e ) {
                }
                catch ( ClassNotFoundException e ) {
                }
            }
            return null;
        }
    });
}

static void hackAndroid23(final String name,
    final android.util.AttributeSet attrs, final LayoutInflater f,
    final TextView[] view) {
    // mConstructorArgs[0] is only non-null during a running call to inflate()
    // so we make a call to inflate() and inside that call our dully XmlPullParser get's called
    // and inside that it will work to call "f.createView( name, null, attrs );"!
    try {
        f.inflate(new XmlPullParser() {
            @Override
            public int next() throws XmlPullParserException, IOException {
                try {
                    view[0] = (TextView) f.createView( name, null, attrs );
                } catch (InflateException e) {
                } catch (ClassNotFoundException e) {
                }
                throw new XmlPullParserException("exit");
            }   
        }, null, false);
    } catch (InflateException e1) {
        // "exit" ignored
    }
}

L'ho testato per funzionare su Android 2.3 e per funzionare ancora sulle versioni precedenti. Se qualcosa si rompe di nuovo nelle versioni successive di Android, vedrai semplicemente lo stile di menu predefinito


Questo codice funziona solo fino alla versione 2.1 Questo codice qui sembra essere migliore: stackoverflow.com/questions/2944244/…
Felipe Caldas

Ciao, ho usato la tua funzione ma ho ricevuto questo seguente errore Errore durante il gonfiaggio della classe com.android.internal.view.menu.IconMenuItemView e un'altra eccezione Errore durante il gonfiaggio della classe <sconosciuto> ... ora cosa dovrei fare ora ... ? mi aiuti per favore.
Rushabh Patel,

13

Mi sono appena imbattuto anche in questo problema, su un'app che doveva essere compatibile con Gingerbread e mantenere il più possibile lo stile dei dispositivi compatibili con Holo.

Ho trovato una soluzione relativamente pulita, che ha funzionato bene per me.

Nel tema utilizzo uno sfondo disegnabile a 9 patch per ottenere un colore di sfondo personalizzato:

<style name="Theme.Styled" parent="Theme.Sherlock">
   ...
   <item name="android:panelFullBackground">@drawable/menu_hardkey_panel</item>
</style>

Ho smesso di provare a modellare il colore del testo e ho semplicemente usato uno Spannable per impostare il colore del testo per il mio articolo nel codice:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
   MenuInflater inflater = getSupportMenuInflater();
   inflater.inflate(R.menu.actions_main, menu);

   if (android.os.Build.VERSION.SDK_INT < 
        android.os.Build.VERSION_CODES.HONEYCOMB) {

        SpannableStringBuilder text = new SpannableStringBuilder();
        text.append(getString(R.string.action_text));
        text.setSpan(new ForegroundColorSpan(Color.WHITE), 
                0, text.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

        MenuItem item1 = menu.findItem(R.id.action_item1);
        item1.setTitle(text);
   }

   return true;
}

funziona alla grande per il mio problema con l'utilizzo del tema ActionBarSherlock Light su un dispositivo Gingerbread! Con questo, posso facilmente cambiare lo sfondo del menu delle opzioni in grigio chiaro e il colore del testo in nero (le icone sono già nere come nella ActionBar! Grazie!
florianbaethge

12

Ecco come ho risolto il mio. Ho appena specificato il colore di sfondo e il colore del testo negli stili. cioè res> valori> file styles.xml.

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:itemBackground">#ffffff</item>
    <item name="android:textColor">#000000</item>
</style>

1
textcolor cambierebbe ovunque
user3156040

cambia solo il colore di sfondo degli elementi e il layout delle opzioni di menu ha un'imbottitura superiore e inferiore, non aiuta
FarshidABZ

10

Una cosa da notare che voi ragazzi state complicando eccessivamente il problema proprio come molti altri post! Tutto quello che devi fare è creare selettori disegnabili con qualsiasi sfondo di cui hai bisogno e impostarli su elementi reali. Ho passato solo due ore a provare le tue soluzioni (tutte suggerite in questa pagina) e nessuna di esse ha funzionato. Per non parlare del fatto che ci sono tonnellate di errori che essenzialmente rallentano le tue prestazioni in quei blocchi try / catch che hai.

Comunque ecco un file xml del menu:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/m1"
          android:icon="@drawable/item1_selector"
          />
    <item android:id="@+id/m2"
          android:icon="@drawable/item2_selector"
          />
</menu>

Ora nel tuo item1_selector:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:drawable="@drawable/item_highlighted" />
    <item android:state_selected="true" android:drawable="@drawable/item_highlighted" />
    <item android:state_focused="true" android:drawable="@drawable/item_nonhighlighted" />
    <item android:drawable="@drawable/item_nonhighlighted" />
</selector>

La prossima volta che decidi di andare al supermercato attraverso il Canada prova google maps!


Sono totalmente d'accordo. Perché reinventare Android quando =) esiste già?
Fredrik

Funziona alla grande. Costruisci una lista di livelli disegnabile con la tua icona e lo sfondo desiderato. L'unico problema è che non so se posso cambiare il colore del testo. Pertanto non tutti i colori di sfondo funzionano
Janusz

52
Bello, elegante e totalmente non risolve il problema.
Aea

1
Se non sbaglio, cambia solo lo sfondo dell'icona, non la voce di menu stessa, che rimane bianca.
Jrom

3
Questa non è una risposta alla domanda. Questo è totalmente diverso pensare.
Kostadin

4
 <style name="AppThemeLight" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:itemBackground">#000000</item>
</style>

questo funziona bene per me


come cambiare il colore del titolo
parvez rafi

3
    /* 
     *The Options Menu (the one that pops up on pressing the menu button on the emulator) 
     * can be customized to change the background of the menu 
     *@primalpop  
   */ 

    package com.pop.menu;

    import android.app.Activity;
    import android.content.Context;
    import android.os.Bundle;
    import android.os.Handler;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.InflateException;
    import android.view.LayoutInflater;
    import android.view.Menu;
    import android.view.MenuInflater;
    import android.view.View;
    import android.view.LayoutInflater.Factory;

    public class Options_Menu extends Activity {

        private static final String TAG = "DEBUG";

        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);

        }

        /* Invoked when the menu button is pressed */

        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // TODO Auto-generated method stub
            super.onCreateOptionsMenu(menu);
            MenuInflater inflater = new MenuInflater(getApplicationContext());
            inflater.inflate(R.menu.options_menu, menu);
            setMenuBackground();
            return true;
        }

        /*IconMenuItemView is the class that creates and controls the options menu 
         * which is derived from basic View class. So We can use a LayoutInflater 
         * object to create a view and apply the background.
         */
        protected void setMenuBackground(){

            Log.d(TAG, "Enterting setMenuBackGround");
            getLayoutInflater().setFactory( new Factory() {

                @Override
                public View onCreateView ( String name, Context context, AttributeSet attrs ) {

                    if ( name.equalsIgnoreCase( "com.android.internal.view.menu.IconMenuItemView" ) ) {

                        try { // Ask our inflater to create the view
                            LayoutInflater f = getLayoutInflater();
                            final View view = f.createView( name, null, attrs );
                            /* 
                             * The background gets refreshed each time a new item is added the options menu. 
                             * So each time Android applies the default background we need to set our own 
                             * background. This is done using a thread giving the background change as runnable
                             * object
                             */
                            new Handler().post( new Runnable() {
                                public void run () {
                                    view.setBackgroundResource( R.drawable.background);
                                }
                            } );
                            return view;
                        }
                        catch ( InflateException e ) {}
                        catch ( ClassNotFoundException e ) {}
                    }
                    return null;
                }
            });
        }
    }

3
Per favore, non farlo: name.equalsIgnoreCase ("com.android.internal.view.menu.IconMenuItemView" Come indica chiaramente il nome, si tratta di dettagli di implementazione privati ​​e quindi può non funzionare su qualsiasi aggiornamento della piattaforma o dispositivo.
hackbod

1
IconMenuItemView è la classe che crea e controlla il menu delle opzioni derivato dalla classe View di base. Questa classe proviene dal codice sorgente di Android ed è presente almeno dalla versione api 5. Non riesco a vederla interrompersi su alcun aggiornamento della piattaforma o dispositivo.
Primal Pappachan

1
Non puoi vederlo perché non puoi vedere il futuro. Anche se ci fosse un modo per essere sicuri, è una cattiva pratica
HXCaine

Grazie, è utile in caso di necessità. Tuttavia, non funziona in casi speciali, come gli elementi creati in onCreateOptionsMenu, ma disabilitati in onPrepareOptionsMenu, ma successivamente abilitati di nuovo.
HRJ

3

Grazie Marcus! Funziona su 2.3 senza problemi correggendo alcuni errori di sintassi, ecco il codice corretto

    protected void setMenuBackground() {
    getLayoutInflater().setFactory(new Factory() {

        @Override
        public View onCreateView(final String name, final Context context,
                final AttributeSet attrs) {

            if (name.equalsIgnoreCase("com.android.internal.view.menu.IconMenuItemView")) {

                try { // Ask our inflater to create the view
                    final LayoutInflater f = getLayoutInflater();
                    final View[] view = new View[1];
                    try {
                        view[0] = f.createView(name, null, attrs);
                    } catch (InflateException e) {
                        hackAndroid23(name, attrs, f, view);
                    }
                    // Kind of apply our own background
                    new Handler().post(new Runnable() {
                        public void run() {
                            view[0].setBackgroundColor(Color.WHITE);

                        }
                    });
                    return view[0];
                } catch (InflateException e) {
                } catch (ClassNotFoundException e) {

                }
            }
            return null;
        }
    });
}

static void hackAndroid23(final String name,
        final android.util.AttributeSet attrs, final LayoutInflater f,
        final View[] view) {
    // mConstructorArgs[0] is only non-null during a running call to
    // inflate()
    // so we make a call to inflate() and inside that call our dully
    // XmlPullParser get's called
    // and inside that it will work to call
    // "f.createView( name, null, attrs );"!
    try {
        f.inflate(new XmlPullParser() {
            @Override
            public int next() throws XmlPullParserException, IOException {
                try {
                    view[0] = (TextView) f.createView(name, null, attrs);
                } catch (InflateException e) {
                } catch (ClassNotFoundException e) {
                }
                throw new XmlPullParserException("exit");
            }
        }, null, false);
    } catch (InflateException e1) {
        // "exit" ignored
    }
}

1
Tutto quello che ottiene per questo: java.lang.IllegalStateException: Una fabbrica è già stato impostato su questo LayoutInflater
Bostone

per farlo funzionare con ActionBarSherlock e il quadro di compatibilità e di evitare IllegalStateException vedere questo trucco stackoverflow.com/questions/13415284/...
avianey

3
protected void setMenuBackground() {
    getLayoutInflater().setFactory(new Factory() {
        @Override
        public View onCreateView (String name, Context context, AttributeSet attrs) {
            if (name.equalsIgnoreCase("com.android.internal.view.menu.IconMenuItemView")) {
                try {
                    // Ask our inflater to create the view
                    LayoutInflater f = getLayoutInflater();
                    final View view = f.createView(name, null, attrs);
                    // Kind of apply our own background
                    new Handler().post( new Runnable() {
                        public void run () {
                            view.setBackgroundResource(R.drawable.gray_gradient_background);
                        }
                    });
                    return view;
                }
                catch (InflateException e) {
                }
                catch (ClassNotFoundException e) {
                }
            }
            return null;
        }
    });
}

questo è un file XML

gradient 
    android:startColor="#AFAFAF" 
    android:endColor="#000000"
    android:angle="270"
shape

1

Se vuoi impostare un colore arbitrario, questo sembra funzionare piuttosto bene per androidx. Testato su KitKat e Pie. Metti questo nel tuo AppCompatActivity:

@Override public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
    if (name.equals("androidx.appcompat.view.menu.ListMenuItemView") &&
            parent.getParent() instanceof FrameLayout) {
            ((View) parent.getParent()).setBackgroundColor(yourFancyColor);
    }
    return super.onCreateView(parent, name, context, attrs);
}

Questo imposta il colore di android.widget.PopupWindow$PopupBackgroundView, che, come avrai intuito, disegna il colore di sfondo. Non ci sono eccedenze e puoi usare anche colori semitrasparenti.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.