Comment changer la couleur du texte de l'élément de menu dans Android?

175

Puis-je changer la couleur d'arrière-plan d'un élément de menu sous Android?

S'il vous plaît laissez-moi savoir si quelqu'un a une solution à cela. La dernière option sera évidemment de le personnaliser, mais existe-t-il un moyen de changer la couleur du texte sans le personnaliser.

sunil
la source
Quelqu'un peut-il me faire part de la solution à ce problème?
dim
3
voulez-vous changer la couleur du texte, la couleur d'arrière-plan de la vue texte? ou les deux? Les deux sont des choses différentes. Veuillez reformuler la question.
Abhinav Saxena

Réponses:

335

Une simple ligne dans votre thème :)

<item name="android:actionMenuTextColor">@color/your_color</item>
Muhammad Alfaifi
la source
19
REMARQUE: Cela DOIT aller dans la définition du thème principal de votre application, PAS dans le actionBarStylepar exemple. Cela ne fonctionnera pas à l'intérieur actionBarStyle, même si cela semble logique!
Colin M.
47
Pour prendre en charge les versions d'API inférieures, <item name="actionMenuTextColor">@color/your_color</item>n'utilisez pas l'espace de noms Android
alex.p
5
@ColinM. Il doit entrer dans un thème. Si vous définissez un themeattribut sur votre barre d'outils, cela fonctionne.
DariusL
2
Ne fonctionnait pas pour moi avec ou sans android: namespace. Il a été ajouté au thème principal de l'application.
courses le
2
Je suis toujours totalement incapable de changer la couleur du texte. Ma couleur de texte du thème général a juste la préférence. De l'aide? Aucune de ces réponses ne fonctionne.
David P
115

Il semble qu'un

  <item name="android:itemTextAppearance">@style/myCustomMenuTextAppearance</item>

dans mon thème et

   <style name="myCustomMenuTextAppearance" parent="@android:style/TextAppearance.Widget.IconMenu.Item">
        <item name="android:textColor">@android:color/primary_text_dark</item>
    </style>

dans styles.xml, changez le style des éléments de liste mais pas les éléments de menu.

Marcus Wolschon
la source
5
Cela fonctionne très bien pour les éléments de menu contextuel (pas les éléments de menu du bouton de menu), ce que j'ai recherché. Beaucoup plus simple que tout le désordre de LayoutFactory.
chubbsondubs
L' android:itemTextAppearanceattribut ne peut pas être placé dans un style dont le parent est parent="@android:style/Widget.Holo.ListPopupWindow"car il ne sera pas rendu correctement. Il doit être dans un style de haut niveau comme celui dont le parent est android:Theme.Holo.Light.DarkActionBar.
toobsco42
Où dois-je ajouter <item name = "android: itemTextAppearance"> @ style / myCustomMenuTextApearance </item>?
Bagusflyer
@bagusflyer vous devez ajouter cela dans le style racine de votre thème, c'est-à-dire le style enfant de Theme.Holoou Theme.Holo.Light.DarkActionBarou similaire.
Tash Pemhiwa
86

Vous pouvez changer la couleur du MenuItem facilement texte en utilisant SpannableStringau lieu de String.

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.your_menu, menu);

    int positionOfMenuItem = 0; // or whatever...
    MenuItem item = menu.getItem(positionOfMenuItem);
    SpannableString s = new SpannableString("My red MenuItem");
    s.setSpan(new ForegroundColorSpan(Color.RED), 0, s.length(), 0);
    item.setTitle(s);
}
max.mustermann
la source
10
Cela a fonctionné pour moi dans les versions 4.4 et 5+ en utilisant menu.findItem(R.id.menu_item_id);au lieu demenu.getItem()
haagmm
1
A travaillé pour moi aussi [en utilisant findItem (...)].
étourdi le
6
les solutions ne fonctionnent que pour l'élément en débordement .... je ne veux pas changer la couleur de l'élément qui est visible en définissant showAsAction: "always"
Junaid
56

Si vous utilisez la nouvelle barre d'outils, avec le thème Theme.AppCompat.Light.NoActionBar, vous pouvez la styliser de la manière suivante.

 <style name="ToolbarTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:textColorPrimary">@color/my_color1</item>
    <item name="android:textColorSecondary">@color/my_color2</item>
    <item name="android:textColor">@color/my_color3</item>
 </style>`

Selon les résultats que j'ai obtenus,
android:textColorPrimaryla couleur du texte affiche le nom de votre activité, qui est le texte principal de la barre d'outils.

android:textColorSecondaryest la couleur du texte pour le sous-titre et le bouton plus d'options (3 points). (Oui, il a changé sa couleur en fonction de cette propriété!)

android:textColorEst la couleur de tous les autres textes, y compris le menu.

Enfin, définissez le thème sur la barre d'outils

<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    app:theme="@style/ToolbarTheme"
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:minHeight="?attr/actionBarSize"/>
Sudara
la source
Quel élément régit le texte sur les boutons qui sont affichés sous forme d'actions (texte) dans la barre d'outils? Ni android: textColorPrimary, android: textColorSecondary, ni android: textColor ne semblent les affecter.
LarsH
En réponse à ma question dans le commentaire précédent: android:actionMenuTextColor(voir stackoverflow.com/a/5538709/423105 ).
LarsH
32

Si vous utilisez le menu comme, <android.support.design.widget.NavigationView />ajoutez simplement la ligne ci-dessous dans NavigationView:

app:itemTextColor="your color"

Également disponible colorTint pour l'icône, il remplacera également la couleur de votre icône. Pour cela, vous devez ajouter la ligne ci-dessous:

app:itemIconTint="your color"

Exemple:

<android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"

        app:itemTextColor="@color/color_white"
        app:itemIconTint="@color/color_white"

        android:background="@color/colorPrimary"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/nav_header_main"
        app:menu="@menu/activity_main_drawer"/>

J'espère que cela vous aidera.

Mihir Trivedi
la source
Cela a changé les éléments qui sont imbriqués dans un autre élément, mais cela n'a pas changé l'élément contenant d'autres éléments. Tu sais comment je pourrais les changer aussi?
Dinu Nicolae
@DinuNicolae Pouvez-vous poster votre exemple de capture d'écran? Ou fournissez plus de détails.
Mihir Trivedi
J'ai eu <item> <menu> <éléments intérieurs> </menu> </item> et seule la couleur des éléments à l'intérieur a changé
Dinu Nicolae
31

Je l'ai fait par programme comme ceci:

public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.changeip_card_menu, menu); 
    for(int i = 0; i < menu.size(); i++) {
        MenuItem item = menu.getItem(i);
        SpannableString spanString = new SpannableString(menu.getItem(i).getTitle().toString());
        spanString.setSpan(new ForegroundColorSpan(Color.BLACK), 0,     spanString.length(), 0); //fix the color to white
        item.setTitle(spanString);
    }
    return true;
}
Muralikrishna GS
la source
2
votre réponse m'a aidé à définir le texte MenuItem en gras. (s.setSpan (nouveau StyleSpan (android.graphics.Typeface.BOLD), 0, s.length (), 0); Merci!
Arkadiusz Cieśliński
Cette solution a aidé mon problème. J'aime cela car cela ne dépendra pas des conditions liées au thème.
Tomcat
15

comme vous pouvez le voir dans cette question, vous devriez:

<item name="android:textColorPrimary">yourColor</item>

Le code ci-dessus modifie la couleur du texte des éléments d'action de menu pour API> = v21.

<item name="actionMenuTextColor">@android:color/holo_green_light</item>

Ci-dessus, le code de l'API <v21

Pouya Danesh
la source
Je vous remercie. Cela devrait être accepté. C'est simple et facile
Pooja
10

J'ai utilisé la balise html pour changer la couleur du texte d'un seul élément lorsque l'élément de menu est gonflé. J'espère que ce serait utile.

public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_main, menu);
    menu.findItem(R.id.main_settings).setTitle(Html.fromHtml("<font color='#ff3824'>Settings</font>"));
    return true;
}
alijandro
la source
1
Cela ne fonctionne pas pour moi sur Marshmallow. Le texte est appliqué, mais pas la couleur.
Ollie C
En ce qui concerne Marshmallow, cela ne fonctionne probablement pas pour la même raison que celle indiquée dans la réponse de max.mustermann, «les solutions ne fonctionnent que pour l'élément en débordement».
Jose_GD
10

Le moyen le plus simple de créer une couleur de menu personnalisée pour une seule barre d'outils, pas pour AppTheme

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay.MenuBlue">
        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"/>
    </android.support.design.widget.AppBarLayout>

barre d'outils habituelle sur styles.xml

<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar"/>

notre style de barre d'outils personnalisé

<style name="AppTheme.AppBarOverlay.MenuBlue">
    <item name="actionMenuTextColor">@color/blue</item>
</style>
AndrewS
la source
Fonctionne très bien! Meilleure réponse.
bebe
9

dans Kotlin, j'ai écrit ces extensions:

fun MenuItem.setTitleColor(color: Int) {
    val hexColor = Integer.toHexString(color).toUpperCase().substring(2)
    val html = "<font color='#$hexColor'>$title</font>"
    this.title = html.parseAsHtml()
}           



@Suppress("DEPRECATION")                                                                        
fun String.parseAsHtml(): Spanned {                                                             
    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {                                
        Html.fromHtml(this, Html.FROM_HTML_MODE_LEGACY)                                         
    } else {                                                                                    
        Html.fromHtml(this)                                                                     
    }                                                                                           
}  

et utilisé comme ceci:

menu.findItem(R.id.main_settings).setTitleColor(Color.RED)
Amir Khorsandi
la source
Vraiment cette solution, très soignée!
Jamil Nawaz
Merci, solution simple et rapide. Pour API> 24, cela fonctionne sans cette deuxième fonction ext
laszlo
7

La reponse courte est oui. Quel chanceux êtes-vous!
Pour ce faire, vous devez remplacer certains styles des styles par défaut d'Android:

Tout d'abord, regardez la définition des thèmes sous Android:

<style name="Theme.IconMenu">
<!-- Menu/item attributes -->
<item name="android:itemTextAppearance">@android:style/TextAppearance.Widget.IconMenu.Item</item>
<item name="android:itemBackground">@android:drawable/menu_selector</item>
<item name="android:itemIconDisabledAlpha">?android:attr/disabledAlpha</item>
<item name="android:horizontalDivider">@android:drawable/divider_horizontal_bright</item>
<item name="android:verticalDivider">@android:drawable/divider_vertical_bright</item>
<item name="android:windowAnimationStyle">@android:style/Animation.OptionsPanel</item>
<item name="android:moreIcon">@android:drawable/ic_menu_more</item>
<item name="android:background">@null</item>
</style>

Ainsi, l'apparence du texte dans le menu est dans @android:style/TextAppearance.Widget.IconMenu.Item
Maintenant, dans la définition des styles :

<style name="TextAppearance.Widget.IconMenu.Item" parent="TextAppearance.Small">
<item name="android:textColor">?textColorPrimaryInverse</item>
</style>

Nous avons donc maintenant le nom de la couleur en question, si vous regardez dans le dossier des couleurs des ressources du système:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="false" android:color="@android:color/bright_foreground_light_disabled" /> 
<item android:state_window_focused="false" android:color="@android:color/bright_foreground_light" /> 
<item android:state_pressed="true" android:color="@android:color/bright_foreground_light" /> 
<item android:state_selected="true" android:color="@android:color/bright_foreground_light" /> 
<item android:color="@android:color/bright_foreground_light" /> 
<!--  not selected --> 
</selector>

Enfin, voici ce que vous devez faire:

Remplacez "TextAppearance.Widget.IconMenu.Item" et créez votre propre style. Ensuite, liez-le à votre propre sélecteur pour le rendre comme vous le souhaitez. J'espère que cela vous aide. Bonne chance!

Sephy
la source
Merci d'avoir répondu. J'ai fait ce que vous avez suggéré mais cela ne change pas la couleur de l'élément de menu
sunil
En fait, je viens de me rendre compte en lisant plus de choses sur le menu que c'est beaucoup plus compliqué que je ne le pensais. vous avez posté ici si je trouve plus.
Sephy
Il n'est pas possible de remplacer "TextAppearance.Widget.IconMenu.Item".
peceps
Cette réponse est trompeuse ... donc la conclusion est que cela ne fonctionne pas et qu'il est beaucoup plus difficile / long à réaliser qu'on ne le pensait à l'origine?
speedynomads
6

Le menu d'options d'Android peut être personnalisé pour définir l'arrière-plan ou modifier l'apparence du texte. L'arrière-plan et la couleur du texte dans le menu ne pouvaient pas être modifiés à l'aide de thèmes et de styles. Le code source Android (data \ res \ layout \ icon_menu_item_layout.xml) utilise un élément personnalisé de la classe "com.android.internal.view.menu.IconMenuItem" View pour la disposition du menu. Nous pouvons apporter des modifications dans la classe ci-dessus pour personnaliser le menu. Pour obtenir la même chose, utilisez la classe d'usine LayoutInflater et définissez l'arrière-plan et la couleur du texte de la vue.


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.my_menu, menu);
    getLayoutInflater().setFactory(new Factory() {
        @Override
        public View onCreateView(String name, Context context, AttributeSet attrs) {
            if (name .equalsIgnoreCase(“com.android.internal.view.menu.IconMenuItemView”)) {
                try{
                    LayoutInflater f = getLayoutInflater();
                    final View view = f.createView(name, null, attrs);
                    new Handler().post(new Runnable() {
                        public void run() {
                            // set the background drawable
                            view .setBackgroundResource(R.drawable.my_ac_menu_background);

                            // set the text color
                            ((TextView) view).setTextColor(Color.WHITE);
                        }
                    });
                    return view;
                } catch (InflateException e) {
                    } catch (ClassNotFoundException e) {}
            }
            return null;
        }
    });
    return super.onCreateOptionsMenu(menu);
}


Abhay Kumar
la source
3
03-23 19:45:25.134: E/AndroidRuntime(26761): java.lang.IllegalStateException: A factory has already been set on this LayoutInflater
To Kra
Cela fonctionne pour la première fois. Lorsque vous ouvrez le menu pour la deuxième fois, vous obtenez une exception.
LoveForDroid
6

Merci pour l'exemple de code. J'ai dû le modifier pour le faire fonctionner avec un menu contextuel. C'est ma solution.

    static final Class<?>[] constructorSignature = new Class[] {Context.class, AttributeSet.class};

class MenuColorFix implements LayoutInflater.Factory {
    public View onCreateView(String name, Context context, AttributeSet attrs) {
        if (name.equalsIgnoreCase("com.android.internal.view.menu.ListMenuItemView")) {
            try {
                Class<? extends ViewGroup> clazz = context.getClassLoader().loadClass(name).asSubclass(ViewGroup.class);
                Constructor<? extends ViewGroup> constructor = clazz.getConstructor(constructorSignature);
                final ViewGroup view = constructor.newInstance(new Object[]{context,attrs});

                new Handler().post(new Runnable() {
                    public void run() {
                        try {
                            view.setBackgroundColor(Color.BLACK);
                            List<View> children = getAllChildren(view);
                            for(int i = 0; i< children.size(); i++) {
                                View child = children.get(i);
                                if ( child instanceof TextView ) {
                                    ((TextView)child).setTextColor(Color.WHITE);
                                }
                            }
                        }
                        catch (Exception e) {
                            Log.i(TAG, "Caught Exception!",e);
                        }

                    }
                });
                return view;
            }
            catch (Exception e) {
                Log.i(TAG, "Caught Exception!",e);
            }
        }
        return null;
    }       
}

public List<View> getAllChildren(ViewGroup vg) {
    ArrayList<View> result = new ArrayList<View>();
    for ( int i = 0; i < vg.getChildCount(); i++ ) {
        View child = vg.getChildAt(i);
        if ( child instanceof ViewGroup) {
            result.addAll(getAllChildren((ViewGroup)child));
        }
        else {
            result.add(child);
        }
    }
    return result;
}

@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
    LayoutInflater lInflater = getLayoutInflater();
    if ( lInflater.getFactory() == null ) {
        lInflater.setFactory(new MenuColorFix());
    }
    super.onCreateContextMenu(menu, v, menuInfo);
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.myMenu, menu);
}

Pour moi, cela fonctionne avec Android 1.6, 2.03 et 4.03.

Michael Vogl
la source
Si vous faites ce qui précède, vous devriez simplement regarder à l'aide de la solution Marcus Wolschon. Beaucoup plus simple.
chubbsondubs
La solution xml ne fonctionne pas pour moi par exemple sur 2.3.x, mais cela fonctionne comme un charme - également sur 4.x
sunlock
Cette solution a fonctionné le mieux. Je devais également capturer android.support.v7.internal.view.menu.ListMenuItemView pour obtenir les styles appliqués sur les appareils utilisant la bibliothèque de compatibilité
Chiatar
Ce correctif ne fonctionnera pas avec Google Maps v2 - la super méthode doit être appelée en premier pour que les cartes s'affichent correctement.
Chiatar
5

je l'ai trouvé Eureka !!

dans le thème de votre application:

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="android:actionBarStyle">@style/ActionBarTheme</item>
    <!-- backward compatibility -->          
    <item name="actionBarStyle">@style/ActionBarTheme</item>        
</style>

voici votre thème de barre d'action:

<style name="ActionBarTheme" parent="@style/Widget.AppCompat.Light.ActionBar.Solid.Inverse">
   <item name="android:background">@color/actionbar_bg_color</item>
   <item name="popupTheme">@style/ActionBarPopupTheme</item
   <!-- backward compatibility -->
   <item name="background">@color/actionbar_bg_color</item>
</style>

et voici votre thème popup:

 <style name="ActionBarPopupTheme">
    <item name="android:textColor">@color/menu_text_color</item>
    <item name="android:background">@color/menu_bg_color</item>
 </style>

À votre santé ;)

Tarif Alnamrouti
la source
5

pour changer la couleur du texte des éléments de menu, utilisez le code ci-dessous

<style name="AppToolbar" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:itemTextAppearance">@style/menu_item_color</item>
</style>

<style name="menu_item_color">
<item name="android:textColor">@color/app_font_color</item>
</style>
Muhammad Abdullah
la source
4

Grâce à max.musterman, voici la solution que j'ai eue pour travailler au niveau 22:

public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu_main, menu);
    SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
    MenuItem searchMenuItem = menu.findItem(R.id.search);
    SearchView searchView = (SearchView) searchMenuItem.getActionView();
    searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
    searchView.setSubmitButtonEnabled(true);
    searchView.setOnQueryTextListener(this);
    setMenuTextColor(menu, R.id.displaySummary, R.string.show_summary);
    setMenuTextColor(menu, R.id.about, R.string.text_about);
    setMenuTextColor(menu, R.id.importExport, R.string.import_export);
    setMenuTextColor(menu, R.id.preferences, R.string.settings);
    return true;
}

private void setMenuTextColor(Menu menu, int menuResource, int menuTextResource) {
    MenuItem item = menu.findItem(menuResource);
    SpannableString s = new SpannableString(getString(menuTextResource));
    s.setSpan(new ForegroundColorSpan(Color.BLACK), 0, s.length(), 0);
    item.setTitle(s);
}

Le codé en dur Color.BLACKpourrait devenir un paramètre supplémentaire de la setMenuTextColorméthode. De plus, je ne l'ai utilisé que pour les éléments de menu qui l'étaient android:showAsAction="never".

gardien de phare
la source
Ne fonctionne pas pour moi sur l'API 24. Des idées? J'étais coincé là-dessus pendant des jours ... ridicule!
David P
Je ne sais pas quoi te dire. Cela fonctionne très bien pour moi dans l'API 25.
lightkeeper
3

Vous pouvez définir la couleur par programmation.

private static void setMenuTextColor(final Context context, final Toolbar toolbar, final int menuResId, final int colorRes) {
    toolbar.post(new Runnable() {
        @Override
        public void run() {
            View settingsMenuItem =  toolbar.findViewById(menuResId);
            if (settingsMenuItem instanceof TextView) {
                if (DEBUG) {
                    Log.i(TAG, "setMenuTextColor textview");
                }
                TextView tv = (TextView) settingsMenuItem;
                tv.setTextColor(ContextCompat.getColor(context, colorRes));
            } else { // you can ignore this branch, because usually there is not the situation
                Menu menu = toolbar.getMenu();
                MenuItem item = menu.findItem(menuResId);
                SpannableString s = new SpannableString(item.getTitle());
                s.setSpan(new ForegroundColorSpan(ContextCompat.getColor(context, colorRes)), 0, s.length(), 0);
                item.setTitle(s);
            }

        }
    });
}
Victor Choy
la source
3

L'ajout de ceci dans mon styles.xml a fonctionné pour moi

<item name="android:textColorPrimary">?android:attr/textColorPrimaryInverse</item>
Asim
la source
2

Ajoutez simplement ceci à votre thème

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="android:itemTextAppearance">@style/AppTheme.ItemTextStyle</item>
</style>

<style name="AppTheme.ItemTextStyle" parent="@android:style/TextAppearance.Widget.IconMenu.Item">
        <item name="android:textColor">@color/orange_500</item>
</style>

Testé sur l'API 21

Pham Quan
la source
2
Il est préférable d'utiliser <style name="AppTheme.ItemTextStyle" parent="@android:style/TextAppearance.Widget">, sinon le texte apparaît trop petit dans le menu de débordement. Notez également que cette technique ne fonctionne que sur Android 5 et supérieur.
Mr-IDE
2
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.search, menu);


    MenuItem myActionMenuItem = menu.findItem( R.id.action_search);
    SearchView searchView = (SearchView) myActionMenuItem.getActionView();

    EditText searchEditText = (EditText) searchView.findViewById(android.support.v7.appcompat.R.id.search_src_text);
    searchEditText.setTextColor(Color.WHITE); //You color here
Bäda
la source
1
expliquez votre réponse
Coder
1
Et si ce n'est pas un SearchView?
nasch le
2

Ma situation était la couleur du texte des paramètres dans le menu des options (le menu principal de l'application était affiché en appuyant sur le bouton du menu).

Testé dans l' API 16 avec la bibliothèque appcompat-v7-27.0.2 , AppCompatActivitypour MainActivityet le AppCompatthème de l'application dans AndroidManifest.xml .

styles.xml :

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
  <item name="actionBarPopupTheme">@style/PopupTheme</item>
</style>

<style name="PopupTheme" parent="@style/ThemeOverlay.AppCompat.Light">
  <item name="android:textColorSecondary">#f00</item>
</style>

Je ne sais pas si cela textColorSecondaryaffecte d'autres éléments, mais cela contrôle la couleur du texte du menu.


J'ai cherché des exemples sur le sujet, mais tous les extraits prêts à l'emploi n'ont pas fonctionné.

J'ai donc voulu l'étudier avec le code source de la bibliothèque appcompat-v7 (en particulier avec le res dossier du package .aar ).

Bien que dans mon cas, j'ai utilisé Eclipse avec des dépendances .aar éclatées . Je pourrais donc changer les styles par défaut et vérifier les résultats. Je ne sais pas comment exploser les bibliothèques à utiliser avec Gradle directement ou Android Studio . Cela mérite un autre fil d’enquête.

Donc mon but était de trouver quelle couleur dans le fichier res / values ​​/ values.xml est utilisée pour le texte du menu (j'étais presque sûr que la couleur était là).

  1. J'ai ouvert ce fichier, puis dupliqué toutes les couleurs, les ai placées sous celles par défaut pour les remplacer et assignées #f00 valeur.
  2. Démarrez l'appli.
  3. De nombreux éléments avaient un fond rouge ou une couleur de texte. Et les éléments de menu aussi. C'était ce dont j'avais besoin.
  4. En supprimant mes couleurs ajoutées par blocs de 5 à 10 lignes, j'ai terminé avec le secondary_text_default_material_light élément de couleur.
  5. En recherchant ce nom dans les fichiers du dossier res (ou mieux dans res / colors ), je n'ai trouvé qu'une seule occurrence dans le fichier color / abc_secondary_text_material_light.xml (j'ai utilisé Sublime Text pour ces opérations, il est donc plus facile de trouver ce dont j'ai besoin).
  6. Retour aux valeurs.xml 8 utilisations ont été trouvées pour le @color/abc_secondary_text_material_light.
  7. C'était un thème Light donc 4 sont partis en 2 thèmes: Base.ThemeOverlay.AppCompat.Lightet Platform.AppCompat.Light.
  8. Le premier thème était un enfant du second, il n'y avait donc que 2 attributs avec cette ressource de couleur: android:textColorSecondaryet android:textColorTertiarydans le Base.ThemeOverlay.AppCompat.Light.
  9. En changeant leurs valeurs directement dans le values.xml et en exécutant l'application, j'ai trouvé que l'attribut final correct était android:textColorSecondary.
  10. Ensuite, j'avais besoin d'un thème ou d'un autre attribut pour pouvoir le changer dans le style.xml de mon application (car mon thème avait comme parent le Theme.AppCompat.Lightet non le ThemeOverlay.AppCompat.Light).
  11. J'ai cherché dans le même fichier le fichier Base.ThemeOverlay.AppCompat.Light. Il a eu un enfantThemeOverlay.AppCompat.Light .
  12. En recherchant le, ThemeOverlay.AppCompat.Lightj'ai trouvé son utilisation dans le Base.Theme.AppCompat.Light.DarkActionBarthème en tant queactionBarPopupTheme valeur d'attribut.
  13. Le thème de mon application Theme.AppCompat.Light.DarkActionBarétait un enfant de celui trouvé Base.Theme.AppCompat.Light.DarkActionBarafin que je puisse utiliser cet attribut dans mon styles.xml sans problème.
  14. Comme on le voit dans l'exemple de code ci-dessus, j'ai créé un thème enfant à partir du thème mentionné ThemeOverlay.AppCompat.Lightet changé l' android:textColorSecondaryattribut.

https://i.imgur.com/LNfKdzC.png

mortalis
la source
1

La solution de Sephy ne fonctionne pas. Il est possible de remplacer l'apparence du texte de l'élément de menu d'options en utilisant la méthode décrite ci-dessus, mais pas l'élément ou le menu. Pour ce faire, il existe essentiellement 3 façons:

  1. Comment changer la couleur de fond du menu des options?
  2. Écrivez votre propre vue pour afficher et remplacer onCreateOptionsMenu et onPrepareOptionsMenu pour obtenir les résultats souhaités. Je le déclare généralement parce que vous pouvez généralement faire ce que vous voulez dans ces méthodes, mais vous ne voudrez probablement pas appeler super ().
  3. Copiez le code du SDK open-source et personnalisez-le en fonction de votre comportement. L'implémentation de menu par défaut utilisée par Activity ne s'appliquera plus.

Voir Problème 4441: Thème du menu d'options personnalisées pour plus d'indices.

Tenace
la source
Pour réitérer ... La solution de Sephy fonctionne pour l'élément de menu TextAppearance, bien que ce que j'ai fait soit de remplacer la valeur par défaut via un themes.xml. De plus, le n ° 2 ou le n ° 3 ci-dessus doit être conscient que l'appel à super # onCreateOptionsMenu / super # onPrepareOptionsMenu est conçu pour placer des éléments de menu système ... comme indiqué dans le javadoc pour Activity # onCreateOptionsMenu (). Cela peut / peut ne pas avoir d'importance pour votre application.
Tenacious
Ce que Sephy décrit est d'avoir ceci dans votre themes.xml: <item name = "android: itemTextAppearance"> @ style / Text_MenuItemText </item> Puis définissez quelque chose comme ceci dans votre styles.xml: <style name = "Text_MenuItemText" > <item name = "android: textSize"> 12dp </item> <item name = "android: textColor"> # FFFFFF </item> </style> C'est aussi simple que possible. C'est ce que tu voulais dire? La personnalisation plus approfondie du menu d'options n'est pas du tout facile, mais j'ai l'intention de publier un article de blog à ce sujet bientôt.
Tenacious
1

essayez ce code ...

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

        getLayoutInflater().setFactory(new Factory() {
            @Override
            public View onCreateView(String name, Context context,
                    AttributeSet attrs) {

                if (name.equalsIgnoreCase("com.android.internal.view.menu.IconMenuItemView")) {
                    try {
                        LayoutInflater f = getLayoutInflater();
                        final View view = f.createView(name, null, attrs);

                        new Handler().post(new Runnable() {
                            public void run() {

                                // set the background drawable
                                 view.setBackgroundResource(R.drawable.my_ac_menu_background);

                                // set the text color
                                ((TextView) view).setTextColor(Color.WHITE);
                            }
                        });
                        return view;
                    } catch (InflateException e) {
                    } catch (ClassNotFoundException e) {
                    }
                }
                return null;
            }
        });
        return super.onCreateOptionsMenu(menu);
    }
Anoop
la source
1
sur Android> 4.0 j'obtiensjava.lang.IllegalStateException: A factory has already been set on this LayoutInflater
To Kra
1

Si vous souhaitez définir la couleur d'un élément de menu individuel, la personnalisation d'un thème de barre d'outils n'est pas la bonne solution. Pour ce faire, vous pouvez utiliser android: actionLayout et une vue d'action pour l'élément de menu.

Créez d'abord un fichier de mise en page XML pour la vue d'action. Dans cet exemple, nous utilisons un bouton comme vue d'action:

menu_button.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/menuButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Done"
        android:textColor="?android:attr/colorAccent"
        style="?android:attr/buttonBarButtonStyle"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Dans l'extrait de code ci-dessus, nous utilisons android:textColor="?android:attr/colorAccent"pour personnaliser la couleur du texte du bouton.

Ensuite, dans votre fichier de mise en page XML pour le menu, incluez app:actionLayout="@layout/menu_button"comme indiqué ci-dessous:

main_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <item
        android:id="@+id/menuItem"
        android:title=""
        app:actionLayout="@layout/menu_button"
        app:showAsAction="always"/>
</menu>

Dernière substitution de la onCreateOptionsMenu()méthode dans votre activité:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main_menu, menu);
    MenuItem item = menu.findItem(R.id.menuItem);
    Button saveButton = item.getActionView().findViewById(R.id.menuButton);
    saveButton.setOnClickListener(view -> {
        // Do something
    });
    return true;
}

... ou fragment:

@Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater){
    inflater.inflate(R.menu.main_menu, menu);
    MenuItem item = menu.findItem(R.id.menuItem);
    Button saveButton = item.getActionView().findViewById(R.id.menuButton);
    button.setOnClickListener(view -> {
        // Do something
    });
}

Pour plus de détails sur les vues d'action, consultez le guide du développeur Android .

Alexander Poleschuk
la source
0

Voici comment colorer un élément de menu spécifique avec de la couleur, fonctionne pour tous les niveaux d'API:

public static void setToolbarMenuItemTextColor(final Toolbar toolbar,
                                               final @ColorRes int color,
                                               @IdRes final int resId) {
    if (toolbar != null) {
        for (int i = 0; i < toolbar.getChildCount(); i++) {
            final View view = toolbar.getChildAt(i);
            if (view instanceof ActionMenuView) {
                final ActionMenuView actionMenuView = (ActionMenuView) view;
                // view children are accessible only after layout-ing
                actionMenuView.post(new Runnable() {
                    @Override
                    public void run() {
                        for (int j = 0; j < actionMenuView.getChildCount(); j++) {
                            final View innerView = actionMenuView.getChildAt(j);
                            if (innerView instanceof ActionMenuItemView) {
                                final ActionMenuItemView itemView = (ActionMenuItemView) innerView;
                                if (resId == itemView.getId()) {
                                    itemView.setTextColor(ContextCompat.getColor(toolbar.getContext(), color));
                                }
                            }
                        }
                    }
                });
            }
        }
    }
}

En faisant cela, vous perdez l'effet de sélecteur d'arrière-plan, voici donc le code pour appliquer un sélecteur d'arrière-plan personnalisé à tous les enfants d'élément de menu.

public static void setToolbarMenuItemsBackgroundSelector(final Context context,
                                                         final Toolbar toolbar) {
    if (toolbar != null) {
        for (int i = 0; i < toolbar.getChildCount(); i++) {
            final View view = toolbar.getChildAt(i);
            if (view instanceof ImageButton) {
                // left toolbar icon (navigation, hamburger, ...)
                UiHelper.setViewBackgroundSelector(context, view);
            } else if (view instanceof ActionMenuView) {
                final ActionMenuView actionMenuView = (ActionMenuView) view;

                // view children are accessible only after layout-ing
                actionMenuView.post(new Runnable() {
                    @Override
                    public void run() {
                        for (int j = 0; j < actionMenuView.getChildCount(); j++) {
                            final View innerView = actionMenuView.getChildAt(j);
                            if (innerView instanceof ActionMenuItemView) {
                                // text item views
                                final ActionMenuItemView itemView = (ActionMenuItemView) innerView;
                                UiHelper.setViewBackgroundSelector(context, itemView);

                                // icon item views
                                for (int k = 0; k < itemView.getCompoundDrawables().length; k++) {
                                    if (itemView.getCompoundDrawables()[k] != null) {
                                        UiHelper.setViewBackgroundSelector(context, itemView);
                                    }
                                }
                            }
                        }
                    }
                });
            }
        }
    }
}

Voici également la fonction d'assistance:

public static void setViewBackgroundSelector(@NonNull Context context, @NonNull View itemView) {
    int[] attrs = new int[]{R.attr.selectableItemBackgroundBorderless};
    TypedArray ta = context.obtainStyledAttributes(attrs);
    Drawable drawable = ta.getDrawable(0);
    ta.recycle();

    ViewCompat.setBackground(itemView, drawable);
}
boîte
la source
0

Pour changer la couleur du texte, vous pouvez simplement définir une vue personnalisée pour le MenuItem, puis vous pouvez définir la couleur du texte.

Exemple de code: MenuItem.setActionView ()

loisir
la source
Bien que cet extrait de code puisse résoudre la question, inclure une explication contribue vraiment à améliorer la qualité de votre message. N'oubliez pas que vous répondez à la question aux lecteurs à l'avenir, et que ces personnes pourraient ne pas connaître les raisons de votre suggestion de code.
Mischa