web-dev-qa-db-fra.com

Comment personnaliser l'arrière-plan et la couleur du texte de l'élément dans NavigationView?

Je veux réaliser quelque chose comme ce qui est montré dans les documents Material Design .

colorControlHighlight est utilisé pour l’arrière-plan des éléments cochés.

J'ai besoin de personnaliser:

  • fond décoché
  • couleur du texte cochée
  • couleur du texte décochée
71
Xan

NavigationDrawer (NavigationView) propose trois options pour la configuration des éléments cochés/sélectionnés.

app:itemIconTint="@color/menu_text_color" //icon color
app:itemTextColor="@color/menu_text_color" //text color
app:itemBackground="@drawable/menu_background_color" //background

Couleur des icônes et du texte

Les deux premières options (icône et texte) nécessitent une ressource de liste d'états de couleurs - https://developer.Android.com/guide/topics/resources/color-list-resource.html

Cette ressource menu_text_color doit être créée dans res/color. Le contenu de ce fichier doit ressembler à:

<!-- res/color/menu_text_color.xml -->
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
  <item Android:color="@color/colorWhite" Android:state_checked="true" />
  <item Android:color="@color/colorBlack" Android:state_checked="false"/>
</selector>
  • @color/colorWhite - ressource de couleur utilisée pour l'élément vérifié

  • @color/colorBlack - ressource de couleur utilisée pour l'élément non vérifié

J'ai créé une ressource pour les deux, mais il est possible de créer deux fichiers séparés: un pour le texte et un pour l'icône.

Arrière-plan (itemBackground)

L'option Arrière-plan nécessite des ressources utilisables au lieu de la couleur. Chaque tentative de définition de la couleur se terminera par une exception. Les ressources pouvant être dessinées doivent être créées dans res/drawable et son contenu doit ressembler à ceci:

<!-- res/drawable/menu_background_color.xml -->
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
  <item Android:drawable="@Android:color/transparent"  Android:state_checked="false"/>
  <item Android:drawable="@color/colorPrimary" Android:state_checked="true"/>
</selector>

Il n’est pas nécessaire de créer des dessinables simulant la couleur (dans d’autres solutions, j’ai vu de telles propositions - peut-être pour les versions antérieures de SDK), la couleur peut être utilisée directement dans ce fichier. Dans cet exemple de fichier, j'utilise la couleur transparente pour l'élément non vérifié et colorPrimary pour l'élément vérifié.

Dépannage et notes importantes

  • Dans les ressources en arrière-plan, utilisez toujours state_checked = "false" au lieu de la valeur par défaut. Avec la couleur par défaut, cela ne fonctionnera pas.
  • Pour le menu dynamique/créé par programme n'oubliez pas de définir les éléments comme vérifiables:

Exemple de code (élément de menu dynamique add): 

  menu.add(group_id, item_id, Menu.NONE, item_name).setCheckable(true).setChecked(false);

Si les éléments ne peuvent pas être cochés, l'arrière-plan ne fonctionnera pas (la couleur du texte et des icônes surprenant fonctionnera comme prévu).

83
Maciej Sikora

itemBackground, itemIconTint et itemTextColor sont de simples attributs xml qui peuvent être définis, bien que vous deviez utiliser un préfixe personnalisé au lieu de Android:

Exemple

<Android.support.v4.widget.DrawerLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    Android:id="@+id/drawer_layout"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:fitsSystemWindows="true">

    <!-- Other layout views -->

    <Android.support.design.widget.NavigationView
        Android:id="@+id/nav_view"
        Android:layout_width="wrap_content"
        Android:layout_height="match_parent"
        Android:layout_gravity="start"
        Android:fitsSystemWindows="true"
        app:itemBackground="@drawable/my_ripple"
        app:itemIconTint="#2196f3"
        app:itemTextColor="#009688"
        app:headerLayout="@layout/nav_header"
        app:menu="@menu/drawer_view" />

</Android.support.v4.widget.DrawerLayout>

Remarque: Dans ce cas, la couleur du texte, la teinte de l'icône et l'arrière-plan sont statiques. Si vous souhaitez modifier la couleur du texte (par exemple, le rose quand il est décoché et le bleu sarcelle quand il est coché), vous devez utiliser un ColorStateList.

Exemple

Créez un nouveau fichier * .xml dans /res/color - appelons-le state_list.xml - avec le contenu suivant:

<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <!-- This is used when the Navigation Item is checked -->
    <item Android:color="#009688" Android:state_checked="true" />
    <!-- This is the default text color -->
    <item Android:color="#E91E63" />
</selector>

et ensuite simplement le référencer comme ceci: app:itemTextColor="@color/state_list"

Il en va de même pour itemIconTint. itemBackground attend un identifiant de ressource. Voir aussi le docs .

125
reVerse

L'utilisation de colorControlHighlight est une bonne solution pour moi. Sachez qu'avec la dernière bibliothèque de support, vous pouvez définir un thème (pas seulement le style) pour chaque widget. Par exemple, vous pouvez définir colorControlHighlight dans le thème NavigationView et cela ne sera pas appliqué au reste des widgets.

7
Mimmo Grottoli

Si vous souhaitez modifier une seule couleur d'élément de menu à partir de votre activité en fonction d'événements, consultez le blog de HANIHASHEMI:

https://hanihashemi.com/2017/05/06/change-text-color-of-menuitem-in-navigation-drawer/

private void setTextColorForMenuItem(MenuItem menuItem, @ColorRes int color) {
  SpannableString spanString = new SpannableString(menuItem.getTitle().toString());
  spanString.setSpan(new ForegroundColorSpan(ContextCompat.getColor(this, color)), 0, spanString.length(), 0);
  menuItem.setTitle(spanString);
}

Méthode d'appel

setTextColorForMenuItem(item, R.color.colorPrimary);

Si vous travaillez avec Xamarin Android, essayez ceci:

private void SetTextColorForMenuItem(IMenuItem menuItem, Android.Graphics.Color color)
        {
            SpannableString spanString = new SpannableString(menuItem.TitleFormatted.ToString());
            spanString.SetSpan(new ForegroundColorSpan(color), 0, spanString.Length(), 0);
            menuItem.SetTitle(spanString);
        }

Méthode d'appel:

SetTextColorForMenuItem(navigationView.Menu.GetItem(0), Android.Graphics.Color.OrangeRed);
3
Jhon

Vous pouvez utiliser par programmation ce code:

int[][] states = new int[][] {
    new int[] { Android.R.attr.state_enabled}, // enabled
    new int[] {-Android.R.attr.state_enabled}, // disabled
    new int[] {-Android.R.attr.state_checked}, // unchecked
    new int[] { Android.R.attr.state_pressed}  // pressed
};

int[] colors = new int[] {
    Color.BLACK,
    Color.RED,
    Color.GREEN,
    Color.BLUE
};

ColorStateList myList = new ColorStateList(states, colors);

  nav_view.setItemIconTintList(myList);
3
Ahmad Aghazadeh

Maintenant, en vue de navigation, vous pouvez également fournir votre propre vue d'élément. Avec le nouveau appcompat-v7:23.1.0, vous pouvez 

définir des vues personnalisées pour les éléments via app: actionLayout ou à l'aide de MenuItemCompat.setActionView ().

View view = View.inflate(context, R.layout.your_custom_nav_layout_item, null);
MenuItemCompat.setActionView(menuItem, view); 

De cette façon, vous pouvez créer votre propre mise en page avec TextView et changer backgrounds/colors/fonts comme bon vous semble. J'espère que cela a été utile:) La source

2
hkop

Vous pouvez le faire en utilisant la déclaration suivante:

navigationView.setItemBackground(ContextCompat.getDrawable(CustomerHomeActivity.this, R.color.transparent));
0
Sohaib Khalid