web-dev-qa-db-fra.com

Changer la couleur d'un élément de menu coché dans un tiroir de navigation

J'utilise la nouvelle bibliothèque Android Design Support pour implémenter un tiroir de navigation dans mon application.

Je ne sais pas comment changer la couleur d'un élément sélectionné!

Voici le xml du menu:

<menu xmlns:Android="http://schemas.Android.com/apk/res/Android">
<group Android:checkableBehavior="single">
    <item
        Android:id="@+id/navigation_item_1"
        Android:icon="@drawable/ic_1"
        Android:title="@string/navigation_item_1"/>

    <item
        Android:id="@+id/navigation_item_2"
        Android:icon="@drawable/ic_2"
        Android:title="@string/navigation_item_2"/>
</group>

Et voici le xml navigationview qui est placé à l'intérieur d'un Android.support.v4.widget.DrawerLayout:

<Android.support.design.widget.NavigationView
    Android:id="@+id/activity_main_navigationview"
    Android:layout_width="wrap_content"
    Android:layout_height="match_parent"
    Android:layout_gravity="start"
    app:headerLayout="@layout/drawer_header"
    app:itemIconTint="@color/black"
    app:itemTextColor="@color/primary_text"
    app:menu="@menu/menu_drawer">

    <TextView
        Android:id="@+id/main_activity_version"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_gravity="bottom"
        Android:layout_marginBottom="@dimen/activity_vertical_margin"
        Android:layout_marginLeft="@dimen/activity_horizontal_margin"
        Android:textColor="@color/primary_text" />

</Android.support.design.widget.NavigationView>

Merci de votre aide !

[EDIT] J'ai déjà examiné des solutions telles que celle-ci: Changer la couleur de fond du menu Android .

Cela semble être un sacré bidouillage et je pensais qu'avec la nouvelle bibliothèque de support de conception, quelque chose de plus propre aurait été introduit?

92
Greg

Vous pouvez y parvenir avec Color State Resource . Si vous remarquez à l'intérieur de votre NavigationView que vous utilisez

app:itemIconTint="@color/black"
app:itemTextColor="@color/primary_text"

Ici, au lieu d'utiliser @color/black ou @color/primary_test, utilisez un Color State List Resource. Pour cela, commencez par créer un nouveau xml (par exemple, tiroir_item.xml) dans le répertoire color (qui devrait figurer dans le répertoire res.). Si vous n'avez pas de répertoire nommé color déjà, créez-en un.

Maintenant, à l'intérieur de drawer_item.xml faites quelque chose comme ça

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <item Android:color="checked state color" Android:state_checked="true" />
    <item Android:color="your default color" />
</selector>

La dernière étape serait de changer votre NavigationView

<Android.support.design.widget.NavigationView
    Android:id="@+id/activity_main_navigationview"
    Android:layout_width="wrap_content"
    Android:layout_height="match_parent"
    Android:layout_gravity="start"
    app:headerLayout="@layout/drawer_header"
    app:itemIconTint="@color/drawer_item"  // notice here
    app:itemTextColor="@color/drawer_item" // and here
    app:itemBackground="@Android:color/transparent"// and here for setting the background color to tranparent
    app:menu="@menu/menu_drawer">

Vous pouvez ainsi utiliser des ressources de liste d'états de couleurs distinctes pour IconTint, ItemTextColor, ItemBackground.

Désormais, lorsque vous définissez un élément comme étant coché (soit dans xml, soit par programme), la couleur de cet élément sera différente de celle des éléments non cochés.

226
Sash_KP

Je crois que app:itemBackground s'attend à un dessin. Alors suivez les étapes ci-dessous:

Créez un fichier dessinable highlight_color.xml avec le contenu suivant:

<shape xmlns:Android="http://schemas.Android.com/apk/res/Android" Android:shape="rectangle">
     <solid Android:color="YOUR HIGHLIGHT COLOR"/>
</shape>

Créez un autre fichier pouvant être dessiné nav_item_drawable.xml avec le contenu suivant:

<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
        <item Android:drawable="@drawable/highlight_color" Android:state_checked="true"/>
</selector>

Enfin, ajoutez la balise app:itemBackground dans NavView:

<Android.support.design.widget.NavigationView
Android:id="@+id/activity_main_navigationview"
Android:layout_width="wrap_content"
Android:layout_height="match_parent"
Android:layout_gravity="start"
app:headerLayout="@layout/drawer_header"
app:itemIconTint="@color/black"
app:itemTextColor="@color/primary_text"
app:itemBackground="@drawable/nav_item_drawable"
app:menu="@menu/menu_drawer">

ici, le fichier highlight_color.xml définit une couleur unie pouvant être dessinée pour l’arrière-plan. Plus tard, cette couleur est désignée par le sélecteur nav_item_drawable.xml.

Cela a fonctionné pour moi. Espérons que cela aidera.

********************************************* MIS À JOUR ******************************************* **

Bien que la réponse mentionnée ci-dessus vous donne un contrôle précis sur certaines propriétés, mais la façon dont je vais décrire décrit encore plus SOLIDE et est un peu PLUS COOL.

Vous pouvez donc définir un ThemeOverlay dans le styles.xml de NavigationView, comme suit:

    <style name="ThemeOverlay.AppCompat.navTheme">

        <!-- Color of text and icon when SELECTED -->
        <item name="colorPrimary">@color/color_of_your_choice</item> 

        <!-- Background color when SELECTED -->
        <item name="colorControlHighlight">@color/color_of_your_choice</item> 

    </style>

appliquez maintenant cet objet ThemeOverlay à l'attribut app:theme de NavigationView, comme suit:

<Android.support.design.widget.NavigationView
Android:id="@+id/activity_main_navigationview"
Android:layout_width="wrap_content"
Android:layout_height="match_parent"
Android:layout_gravity="start"
app:theme="@style/ThemeOverlay.AppCompat.navTheme"
app:headerLayout="@layout/drawer_header"
app:menu="@menu/menu_drawer">

J'espère que cela aidera.

57
Ankush

Il est nécessaire de définir NavigateItem cochée à chaque fois qu'un élément de NavigateView est cliqué

//listen for navigation events
NavigationView navigationView = (NavigationView)findViewById(R.id.navigation);
navigationView.setNavigationItemSelectedListener(this);
// select the correct nav menu item
navigationView.getMenu().findItem(mNavItemId).setChecked(true);

Ajouter NavigationItemSelectedListener sur NavigationView

  @Override
  public boolean onNavigationItemSelected(final MenuItem menuItem) {
    // update highlighted item in the navigation menu
    menuItem.setChecked(true);
    mNavItemId = menuItem.getItemId();

    // allow some time after closing the drawer before performing real navigation
    // so the user can see what is happening
    mDrawerLayout.closeDrawer(GravityCompat.START);
    mDrawerActionHandler.postDelayed(new Runnable() {
      @Override
      public void run() {
        navigate(menuItem.getItemId());
      }
    }, DRAWER_CLOSE_DELAY_MS);
    return true;
  }
3
Vikalp Patel

Voici un autre moyen d'y parvenir:

public boolean onOptionsItemSelected(MenuItem item) {

    int id = item.getItemId();

    item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
        @Override
        public boolean onMenuItemClick(MenuItem item) {
            item.setEnabled(true);
            item.setTitle(Html.fromHtml("<font color='#ff3824'>Settings</font>"));
            return false;
            }
        });


    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}

}

2
abhishek pant

Voici comment vous pouvez le faire dans la méthode onCreate de votre activité:

NavigationView navigationView = findViewById(R.id.nav_view);
ColorStateList csl = new ColorStateList(
    new int[][] {
        new int[] {-Android.R.attr.state_checked}, // unchecked
        new int[] { Android.R.attr.state_checked}  // checked
    },
    new int[] {
        Color.BLACK,
        Color.RED
    }
);
navigationView.setItemTextColor(csl);
navigationView.setItemIconTintList(csl);
0
tguen