Ändern Sie die Farbe eines markierten Menüelements in einer Navigationsleiste

103

Ich verwende die neue Android Design Support-Bibliothek, um eine Navigationsleiste in meiner Anwendung zu implementieren.

Ich kann nicht herausfinden, wie ich die Farbe eines ausgewählten Elements ändern kann!

Hier ist die XML des Menüs:

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

Und hier ist die Navigationsansicht-XML, die in einem platziert ist 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>

Danke für Ihre Hilfe !

[BEARBEITEN] Ich habe mir bereits Lösungen wie diese angesehen: Ändern Sie die Hintergrundfarbe des Android-Menüs .

Es scheint ein ziemlicher Hack zu sein und ich dachte, dass mit der neuen Design Support Library etwas Saubereres eingeführt worden wäre?

Greg
quelle
Mögliches Duplikat von Hintergrundfarbe des Android-Menüs
ändern

Antworten:

244

Nun, Sie können dies mit Color State Resource erreichen . Wenn Sie in Ihrem bemerken, verwenden NavigationViewSie

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

Verwenden Sie hier anstelle von @color/blackoder @color/primary_testa Color State List Resource. Erstellen Sie dazu zunächst ein neues xmlVerzeichnis (z. B. drawer_item.xml) color(das sich im resVerzeichnis befinden sollte). Wenn Sie noch kein Verzeichnis mit dem Namen haben color, erstellen Sie eines.

Jetzt drinnen drawer_item.xmlmach so etwas

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

Der letzte Schritt wäre, Ihre zu ändern 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">

So kann man getrennte Farbe Zustand Ressourcen auflisten verwenden für IconTint, ItemTextColor, ItemBackground.

Wenn Sie nun ein Element als aktiviert (entweder in xmloder programmgesteuert) festlegen , hat das jeweilige Element eine andere Farbe als die nicht aktivierten.

Sash_KP
quelle
Denken Sie daran, dass Sie, damit gedrückt wird, von android: state_checked in android: state_pressed geändert werden müssen.
Programista
32
Für ItemBackground müssen Sie anstelle von Farbe ein Zeichenelement verwenden, da Sie mit einer Farbressource keinen Hintergrund definieren können.
SirFunkenstine
@sash Wenn wir das Symbolbild für ein ausgewähltes Navigationselement ändern möchten, wie werden wir dies tun?
Mohit
@sirFunkenstine Wenn Sie die Farbauswahl verwenden, können Sie sie in einem Farbordner in Ihrem Res-Ordner ablegen.
Kishan Vaghela
@KishanVaghela, das zu tun, was Sie vorschlagen, erzeugt diesen Fehler: Binäre XML-Dateizeile # 3: <item> -Tag erfordert ein 'drawable'-Attribut oder ein untergeordnetes Tag, das ein drawable definiert
iOSAndroidWindowsMobileAppsDev
66

Ich glaube app:itemBackgrounderwartet ein Drawable. Befolgen Sie also die folgenden Schritte:

Erstellen Sie eine zeichnbare Datei highlight_color.xmlmit folgenden Inhalten:

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

Erstellen Sie eine weitere zeichnbare Datei nav_item_drawable.xmlmit folgenden Inhalten:

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

app:itemBackgroundFügen Sie zum Schluss ein Tag in NavView hinzu:

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

Hier definiert die Dateilight_color.xml eine Volltonfarbe, die für den Hintergrund gezeichnet werden kann. Später wird diese Farbe dem Selektor nav_item_drawable.xml zugewiesen.

Das hat bei mir funktioniert. Hoffentlich hilft das.

************************************************** AKTUALISIERT *** ***********************************************

Die oben erwähnte Antwort gibt Ihnen zwar eine genaue Kontrolle über einige Eigenschaften, aber die Art und Weise, wie ich sie beschreiben werde, fühlt sich fester an und ist etwas kühler .

Sie können also ein ThemeOverlay in styles.xmlder Navigationsansicht wie folgt definieren :

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

Wenden Sie dieses ThemeOverlay nun wie folgt auf das app:themeAttribut von NavigationView an:

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

Ich hoffe das wird helfen.

Ankush
quelle
1
Diese Methode kann auch android:background="@drawable/nav_item_drawable"für andere Widgets wie RadioButton, Checkbox, Button usw. verwendet werden. Reduziert die Bloatware-Programmierung für die Handhabung setOnCheckedChangeListenernur zur Hervorhebung von Farben.
Rupinderjeet
@Ankush das funktioniert aber Text und Symbol verschwinden, ich habe die Farbe des Artikels auch eingestellt, aber es funktioniert nicht. können Sie mir bitte vorschlagen, wie es gemacht werden kann
Benutzer
1
@Benutzer Ich weiß nicht, was mit Ihrem Code schief gelaufen ist, aber ich habe die Antwort hinzugefügt. Ein ganz anderer Weg, um mit weniger Aufwand dasselbe zu erreichen. Sie können das überprüfen.
Ankush
1
Dies sollte als Antwort akzeptiert werden! Vielen Dank, sehr hilfreich !!!
Svetlana Rozhkova
4

NavigateItemJedes Mal, wenn auf ein Element NavigateViewgeklickt wird, muss das Kontrollkästchen true gesetzt werden

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

Add NavigationItemSelectedListeneronNavigationView

  @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;
  }
Vikalp Patel
quelle
Vielen Dank für Ihre Hilfe Vikalp, aber das mache ich schon ( setChecked(true)). Ich kann sehen, dass sich die Farbe des markierten Elements ändert, aber ich kann es nicht selbst ändern. Die Farbe ist immer eine hellere Version des Navigatioview-Hintergrunds.
Greg
@ Greg standardmäßig setChecked(true)auf ViewÄnderungen Hintergrundfarbe bis zu Thema , das Gerät , das Sie verwendet. Wenn Sie den Hintergrund eines Elements in eine andere Farbe ändern möchten, müssen Sie Ihr Layout in DrawerLayoutoder aufblasen NavigationViewund es selbst handhaben.
Vikalp Patel
Nochmals vielen Dank, ich habe versucht zu tun, was Sie mir gesagt haben, aber ohne Erfolg, hätten Sie einen Link, der erklärt, wie bitte?
Greg
2

Hier ist der andere Weg, um dies zu erreichen:

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

}}

Abhishek
quelle
Mein Problem war, was passiert, wenn ich die Farbe des ausgewählten Popup-Menüelements ändern möchte, aber dank Ihnen habe ich von dieser Lösung eine großartige Idee, die Farbe des ausgewählten Menüelements zu ändern ... also geben Sie Ihre Stimme !!! Und die Problemumgehung ist wie folgt: item.setTitle (Html.fromHtml ("<font color = '# ff3824'> Einstellungen </ font>"));
Tarit Ray
1

So können Sie dies in der onCreate-Methode Ihrer Aktivität tun:

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);
tguen
quelle
1

Schritt 1: Erstellen Sie einen aktivierten / nicht aktivierten Selektor:

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>

Schritt 2: Verwenden Sie das XML-Attribut app:itemTextColorim NavigationViewWidget, um die Textfarbe auszuwählen.

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

Schritt 3:
Wenn Sie aus irgendeinem Grund auf ein Element im NavigationViewMenü klicken, wird dies nicht als Schaltflächenprüfung betrachtet. Sie müssen also das ausgewählte Element manuell überprüfen lassen und das zuvor ausgewählte Element löschen. Verwenden Sie dazu den folgenden Listener

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

Schritt 4:
Um die Symbolfarbe zu ändern, verwenden Sie das app:iconTintAttribut in den NavigationViewMenüelementen und stellen Sie denselben Selektor ein.

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

Ergebnis:

Zain
quelle