Cambia il colore di una voce di menu selezionata in un cassetto di navigazione


103

Sto usando la nuova libreria Android Design Support per implementare un cassetto di navigazione nella mia applicazione.

Non riesco a capire come cambiare il colore di un oggetto selezionato!

Ecco l'xml del 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>

Ed ecco il navigationview xml che si trova all'interno di 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>

Grazie per l'aiuto !

[EDIT] Ho già esaminato soluzioni come questa: cambia il colore di sfondo del menu Android .

Sembra essere un vero trucco e ho pensato che con la nuova Design Support Library, sarebbe stato introdotto qualcosa di più pulito?


Risposte:


244

Bene, puoi ottenere questo risultato usando Color State Resource . Se si nota all'interno della vostra NavigationViewstai usando

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

Qui invece di usare @color/blacko @color/primary_test, usa un file Color State List Resource. Per questo, prima crea una nuova directory xmlinterna (ad esempio drawer_item.xml) color(che dovrebbe essere all'interno della resdirectory). Se non hai colorgià una directory denominata , creane una.

Ora dentro drawer_item.xmlfai qualcosa del genere

<?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>

Il passaggio finale sarebbe cambiare il tuo file 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">

Ti piace questa è possibile utilizzare diversi colori Lista Stato Risorse per IconTint, ItemTextColor, ItemBackground.

Ora, quando si imposta un elemento come selezionato (o in modo xmlprogrammatico), l'elemento specifico avrà un colore diverso da quelli deselezionati.


Ricorda che per far funzionare premuto devi cambiarlo da android: state_checked ad android: state_pressed.
Programista

32
per ItemBackground è necessario utilizzare un disegnabile invece del colore perché non è possibile definire uno sfondo utilizzando una risorsa colore.
sirFunkenstine

@sash se vogliamo cambiare l'immagine dell'icona sulla voce di navigazione selezionata, come lo faremo?
Mohit

@sirFunkenstine Se stai usando il selettore di colori, puoi metterlo nella cartella dei colori nella tua cartella res.
Kishan Vaghela

@KishanVaghela facendo ciò che suggerisci produce questo errore: Riga del file XML binario n. 3: il tag <item> richiede un attributo 'drawable' o un tag figlio che definisce un drawable
iOSAndroidWindowsMobileAppsDev

66

Credo si app:itemBackgroundaspetti un drawable. Quindi segui i passaggi seguenti:

Crea un file disegnabile highlight_color.xmlcon i seguenti contenuti:

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

Crea un altro file disegnabile nav_item_drawable.xmlcon i seguenti contenuti:

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

Infine aggiungi il app:itemBackgroundtag nel 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">

qui il file highlight_color.xml definisce un colore solido disegnabile per lo sfondo. Successivamente questo drawable di colore viene assegnato al selettore nav_item_drawable.xml.

Questo ha funzionato per me. Si spera che questo possa aiutare.

********************************************** AGGIORNATO *** *******************************************

Sebbene la risposta sopra menzionata ti dia un controllo preciso su alcune proprietà, ma il modo in cui sto per descrivere sembra più SOLIDO ed è un po ' PIÙ FREDDO .

Quindi quello che puoi fare è definire un ThemeOverlay nel styles.xmlNavigationView in questo modo:

    <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>

ora applica questo ThemeOverlay app:themeall'attributo di NavigationView, in questo modo:

<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">

Spero che questo ti possa aiutare.


1
Inoltre, questo metodo può essere utilizzato come android:background="@drawable/nav_item_drawable"per altri widget come RadioButton, Checkbox, Button ecc. Riduce la programmazione bloatware per la gestione setOnCheckedChangeListenersolo dell'evidenziazione del colore.
rupinderjeet

@Ankush funziona ma il testo e l'icona scompaiono, ho impostato anche il colore della tinta dell'oggetto ma non funziona. potete suggerirmi come si può fare
Utente

1
@User Non so cosa sia andato storto con il tuo codice, ma ho aggiunto alla risposta. Un modo completamente diverso per ottenere la stessa cosa con meno sforzo. Puoi verificarlo.
Ankush

1
Questa dovrebbe essere accettata come una risposta! Grazie mille, molto utile !!!
Svetlana Rozhkova,

4

È necessario impostare NavigateItemverificato true ogni volta che si NavigateViewfa clic su un elemento

//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);

Aggiungi NavigationItemSelectedListenersuNavigationView

  @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;
  }

Grazie per il tuo aiuto Vikalp, ma lo sto già facendo ( setChecked(true)). Posso vedere il colore dell'elemento selezionato cambiare ma non posso modificarlo da solo, il colore è sempre una versione più chiara dello sfondo della navigazione.
Greg

@Greg Per impostazione predefinita setChecked(true), Viewcambia il colore di sfondo fino al tema del dispositivo che utilizzi. Se vuoi cambiare lo sfondo di un elemento con un altro colore, devi gonfiare il layout in DrawerLayouto NavigationViewe gestirlo da solo.
Vikalp Patel

grazie ancora, ho provato a fare quello che mi hai detto ma senza successo, avresti un link che spieghi come per favore?
Greg

2

Ecco un altro modo per ottenere questo:

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);
}

}


Il mio dobut riguardava cosa succede se volessi cambiare il colore della voce selezionata del menu popup, ma grazie a te che ho avuto una grande idea da questa tua soluzione per cambiare il colore della voce di menu selezionata ... quindi dandoti voto !!! E la soluzione è: item.setTitle (Html.fromHtml ("<font color = '# ff3824'> Impostazioni </font>"));
Tarit Ray

1

Ecco come puoi farlo nel metodo onCreate della tua attività:

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);

1

Passaggio 1: crea un selettore selezionato / deselezionato:

selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/yellow" android:state_checked="true" />
    <item android:color="@color/white" android:state_checked="false" />
</selector>

Passaggio 2: utilizza l'attributo xml app:itemTextColorall'interno del NavigationViewwidget per selezionare il colore del testo.

<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:headerLayout="@layout/navigation_header_layout"
    app:itemTextColor="@drawable/selector"
    app:menu="@menu/navigation_menu" />

Passaggio 3:
per qualche motivo, quando si NavigationViewpreme un elemento dal menu, non viene considerato come un controllo del pulsante. Quindi è necessario controllare manualmente l'elemento selezionato e cancellare l'elemento selezionato in precedenza. Usa l'ascoltatore sotto per farlo

@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {

    int id = item.getItemId();

    // remove all colors of the items to the `unchecked` state of the selector
    removeColor(mNavigationView);

    // check the selected item to change its color set by the `checked` state of the selector
    item.setChecked(true);

    switch (item.getItemId()) {
      case R.id.dashboard:
          ...
    }

    drawerLayout.closeDrawer(GravityCompat.START);
    return true;
}

private void removeColor(NavigationView view) {
    for (int i = 0; i < view.getMenu().size(); i++) {
        MenuItem item = view.getMenu().getItem(i);
        item.setChecked(false);
    }
}

Passaggio 4:
per modificare il colore dell'icona, utilizzare l' app:iconTintattributo nelle NavigationViewvoci di menu e impostare lo stesso selettore.

<?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/nav_account"
        android:checked="true"
        android:icon="@drawable/ic_person_black_24dp"
        android:title="My Account"
        app:iconTint="@drawable/selector" />
    <item
        android:id="@+id/nav_settings"
        android:icon="@drawable/ic_settings_black_24dp"
        android:title="Settings"
        app:iconTint="@drawable/selector" />

    <item
        android:id="@+id/nav_logout"
        android:icon="@drawable/logout"
        android:title="Log Out"
        app:iconTint="@drawable/selector" />
</menu>

Risultato:

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.