Ubah warna item menu yang dicentang di panel samping navigasi

103

Saya menggunakan pustaka Dukungan Desain Android baru untuk mengimplementasikan panel samping navigasi dalam aplikasi saya.

Saya tidak tahu cara mengubah warna item yang dipilih!

Berikut adalah xml dari menu tersebut:

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

Dan berikut adalah navigationview xml yang ditempatkan di dalam 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>

Terima kasih untuk bantuannya !

[EDIT] Saya telah melihat solusi seperti ini: Ubah warna latar belakang menu android .

Tampaknya ini merupakan peretasan dan saya pikir dengan Perpustakaan Dukungan Desain baru, sesuatu yang lebih bersih akan diperkenalkan?

Greg
sumber
kemungkinan duplikat Ubah warna latar belakang menu android
jlopez

Jawaban:

244

Anda dapat mencapai ini menggunakan Color State Resource . Jika Anda melihat di dalam NavigationViewAnda sedang menggunakan

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

Di sini daripada menggunakan @color/blackatau @color/primary_test, gunakan file Color State List Resource. Untuk itu, pertama-tama buat direktori baru xml(misalnya drawer_item.xml) di dalam colordirektori (yang seharusnya ada di dalam resdirektori.) Jika Anda belum memiliki direktori yang colorsudah bernama , buatlah.

Sekarang di dalam drawer_item.xmllakukan sesuatu seperti ini

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

Langkah terakhir adalah mengubah 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">

Seperti ini Anda dapat menggunakan terpisah Warna Negara Daftar Sumber Daya untuk IconTint, ItemTextColor, ItemBackground.

Sekarang ketika Anda menyetel item sebagai dicentang (baik dalam xmlatau secara terprogram), item tertentu akan memiliki warna yang berbeda dari yang tidak dicentang.

Sash_KP
sumber
Ingatlah bahwa agar ditekan agar berfungsi, Anda perlu mengubahnya dari android: state_checked menjadi android: state_pressed.
Programista
32
untuk ItemBackground Anda perlu menggunakan drawable, bukan color, karena Anda tidak bisa menentukan latar belakang menggunakan sumber daya warna.
sirFunkenstine
@sash jika kita ingin melakukan perubahan gambar icon pada item navigasi tertentu lalu bagaimana caranya?
mohit
@sirFunkenstine Jika Anda menggunakan pemilih warna maka Anda dapat memasukkannya ke folder warna di folder res Anda.
Kishan Vaghela
@KishanVaghela melakukan apa yang Anda sarankan menghasilkan kesalahan ini: Baris file XML biner # 3: <item> tag memerlukan atribut 'drawable' atau tag anak yang menentukan
drawable
66

Saya yakin app:itemBackgroundmengharapkan drawable. Jadi ikuti langkah-langkah di bawah ini:

Buat file drawable highlight_color.xmldengan konten berikut:

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

Buat file drawable lain nav_item_drawable.xmldengan konten berikut:

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

Terakhir tambahkan app:itemBackgroundtag di 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">

di sini file highlight_color.xml mendefinisikan drawable warna solid untuk latar belakang. Nanti drawable warna ini ditetapkan ke pemilih nav_item_drawable.xml.

Ini berhasil untuk saya. Semoga ini bisa membantu.

********************************************** DIPERBARUI *** *******************************************

Meskipun jawaban yang disebutkan di atas memberi Anda kendali yang baik atas beberapa properti, tetapi cara yang akan saya gambarkan terasa lebih PADAT dan sedikit LEBIH KEREN .

Jadi yang bisa Anda lakukan adalah, Anda bisa mendefinisikan ThemeOverlay di styles.xmluntuk NavigationView seperti ini:

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

sekarang terapkan ThemeOverlay ini ke app:themeatribut NavigationView, seperti ini:

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

Saya harap ini akan membantu.

Ankush
sumber
1
Selain itu, metode ini dapat digunakan android:background="@drawable/nav_item_drawable"untuk widget lain seperti RadioButton, Checkbox, Button, dll. Mengurangi pemrograman bloatware untuk menangani setOnCheckedChangeListenerhanya untuk penyorotan warna.
rupinderjeet
@Ankush ini berfungsi tetapi teks dan ikon menghilang, saya telah menyetel warna warna item juga tetapi tidak berfungsi. bisakah Anda memberi tahu saya bagaimana hal itu dapat dilakukan
Pengguna
1
@User Saya tidak tahu apa yang salah dengan kode Anda, tetapi saya telah menambahkan jawabannya. Cara yang sama sekali berbeda untuk mencapai hal yang sama dengan sedikit usaha. Anda bisa memeriksanya.
Ankush
1
Ini harus diterima sebagai jawaban! Terima kasih banyak, sangat membantu !!!
Svetlana Rozhkova
4

Satu kebutuhan untuk mengatur NavigateItemcheck true setiap kali item NavigateViewdiklik

//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
sumber
Terima kasih atas bantuan Anda Vikalp, tapi saya sudah melakukan itu ( setChecked(true)). Saya dapat melihat warna item yang dicentang berubah tetapi saya tidak dapat memodifikasinya sendiri, warnanya selalu merupakan versi yang lebih terang dari latar belakang navigasi.
Greg
@Greg Secara default setChecked(true)pada Viewperubahan warna latar hingga tema perangkat yang Anda gunakan. Jika Anda mengubah latar belakang item ke warna lain maka Anda perlu mengembangkan tata letak Anda dalam DrawerLayoutatau NavigationViewdan menangani sendiri.
Vikalp Patel
terima kasih sekali lagi, saya telah mencoba melakukan apa yang Anda katakan tetapi tidak berhasil, apakah Anda akan memiliki tautan yang menjelaskan caranya?
Greg
2

Berikut adalah cara lain untuk mencapai ini:

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
sumber
Dobut saya adalah tentang bagaimana jika saya ingin mengubah warna item menu popup yang dipilih, tetapi terima kasih kepada Anda bahwa saya mendapat satu ide bagus dari solusi Anda ini untuk mengubah warna item menu yang dipilih ... jadi memberi Anda suara !!! Dan penyelesaiannya seperti :: item.setTitle (Html.fromHtml ("<font color = '# ff3824'> Settings </font>"));
Tarit Ray
1

Berikut cara melakukannya dalam metode onCreate Aktivitas Anda:

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

Langkah 1: Buat pemilih yang dicentang / tidak dicentang:

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>

Langkah 2: gunakan atribut xml app:itemTextColordalam NavigationViewwidget untuk memilih warna teks.

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

Langkah 3:
Untuk beberapa alasan ketika Anda menekan item dari NavigationViewmenu, itu tidak menganggap ini sebagai pemeriksaan tombol. Jadi, Anda perlu secara manual memeriksa item yang dipilih dan menghapus item yang dipilih sebelumnya. Gunakan pendengar di bawah ini untuk melakukan itu

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

Langkah 4:
Untuk mengubah warna ikon, gunakan app:iconTintatribut di NavigationViewitem menu, dan setel ke selektor yang sama.

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

Hasil:

Zain
sumber