เปลี่ยนสีของรายการเมนูที่เลือกในลิ้นชักการนำทาง


103

ฉันใช้ไลบรารี Android Design Support ใหม่เพื่อใช้งานลิ้นชักการนำทางในแอปพลิเคชันของฉัน

ฉันคิดไม่ออกว่าจะเปลี่ยนสีของรายการที่เลือกอย่างไร!

นี่คือ xml ของเมนู:

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

และนี่คือ navigationview xml ซึ่งอยู่ใน a 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>

ขอขอบคุณสำหรับความช่วยเหลือของคุณ !

[แก้ไข] ฉันได้ดูแล้วในการแก้ปัญหาเช่นนี้: เปลี่ยนสีพื้นหลังของเมนูหุ่นยนต์

ดูเหมือนว่าจะเป็นการแฮ็คและฉันคิดว่าด้วยไลบรารี Design Support ใหม่จะมีอะไรที่สะอาดกว่านี้มาแนะนำ?


สามารถทำซ้ำได้ของการเปลี่ยนสีพื้นหลังของเมนู Android
jlopez

คำตอบ:


245

ดีที่คุณสามารถบรรลุนี้โดยใช้ทรัพยากรของรัฐสี หากคุณสังเกตเห็นNavigationViewว่าคุณกำลังใช้อยู่

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

ที่นี่แทนที่จะใช้@color/blackหรือ@color/primary_testใช้ไฟล์Color State List Resource. ก่อนอื่นให้สร้างxmlไดเร็กทอรีใหม่(เช่น drawer_item.xml) ภายในcolorไดเร็กทอรี (ซึ่งควรอยู่ในresไดเร็กทอรี) หากคุณยังไม่มีไดเร็กทอรีที่ตั้งชื่อcolorอยู่แล้วให้สร้างไดเร็กทอรี

ตอนนี้ข้างในdrawer_item.xmlทำอะไรแบบนี้

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

ขั้นตอนสุดท้ายคือการเปลี่ยนไฟล์ 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">

เช่นนี้คุณสามารถใช้รายการแยกต่างหากรัฐสีทรัพยากรสำหรับIconTint, ,ItemTextColorItemBackground

ตอนนี้เมื่อคุณตั้งค่ารายการตามที่เลือกไว้ (ทั้งในxmlหรือโดยทางโปรแกรม) รายการนั้น ๆ จะมีสีแตกต่างจากรายการที่ไม่ได้เลือกไว้


โปรดจำไว้ว่าสำหรับการกดเพื่อทำงานคุณต้องเปลี่ยนจาก android: state_checked เป็น android: state_pressed
Programista

32
สำหรับ ItemBackground คุณต้องใช้ drawable แทนสีเนื่องจากคุณไม่สามารถกำหนดพื้นหลังโดยใช้ทรัพยากรสีได้
sirFunkenstine

@sash หากเราต้องการเปลี่ยนภาพไอคอนในรายการนำทางที่เลือกแล้วเราจะทำอย่างไร?
mohit

@sirFunkenstine หากคุณใช้ตัวเลือกสีคุณสามารถวางไว้ในโฟลเดอร์สีในโฟลเดอร์ res ของคุณ
Kishan Vaghela

@KishanVaghela การทำในสิ่งที่คุณแนะนำทำให้เกิดข้อผิดพลาดนี้: ไฟล์ Binary XML บรรทัด # 3: แท็ก <item> ต้องการแอตทริบิวต์ "drawable" หรือแท็กลูกที่กำหนดค่าที่วาดได้
iOSAndroidWindowsMobileAppsDev

67

ฉันเชื่อapp:itemBackgroundว่าคาดว่าจะสามารถเบิกได้ ทำตามขั้นตอนด้านล่าง:

สร้างไฟล์ที่วาดได้highlight_color.xmlโดยมีเนื้อหาดังต่อไปนี้:

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

สร้างไฟล์ที่วาดได้อีกไฟล์nav_item_drawable.xmlโดยมีเนื้อหาต่อไปนี้:

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

สุดท้ายเพิ่มapp:itemBackgroundแท็กใน 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">

ที่นี่ไฟล์ highlight_color.xml กำหนดสีทึบที่วาดได้สำหรับพื้นหลัง ในภายหลังสีที่วาดได้นี้จะถูกกำหนดให้กับตัวเลือก nav_item_drawable.xml

สิ่งนี้ได้ผลสำหรับฉัน หวังว่านี่จะช่วยได้

********************************************** อัพเดท *** *******************************************

แม้ว่าคำตอบที่กล่าวถึงข้างต้นจะช่วยให้คุณสามารถควบคุมคุณสมบัติบางอย่างได้ดี แต่วิธีที่ฉันกำลังจะอธิบายรู้สึกว่าเป็นของแข็งมากกว่าและค่อนข้างเย็นกว่า

สิ่งที่คุณสามารถทำได้คือคุณสามารถกำหนดThemeOverlayในstyles.xmlสำหรับ NavigationView ได้ดังนี้:

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

ตอนนี้ใช้ ThemeOverlay นี้กับapp:themeแอตทริบิวต์ของ 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:theme="@style/ThemeOverlay.AppCompat.navTheme"
app:headerLayout="@layout/drawer_header"
app:menu="@menu/menu_drawer">

ฉันหวังว่านี่จะช่วยได้


1
นอกจากนี้วิธีนี้ยังสามารถใช้กับandroid:background="@drawable/nav_item_drawable"วิดเจ็ตอื่น ๆ เช่น RadioButton, Checkbox, Button เป็นต้นลดการเขียนโปรแกรม bloatware สำหรับการจัดการsetOnCheckedChangeListenerเฉพาะสำหรับการเน้นสี
rupinderjeet

@Ankush ใช้งานได้ แต่ข้อความและไอคอนหายไปฉันได้ตั้งค่าสีอ่อนของรายการด้วย แต่ใช้งานไม่ได้ คุณช่วยแนะนำฉันหน่อยได้ไหมว่ามันทำได้อย่างไร
ผู้ใช้

1
@ ผู้ใช้ฉันไม่รู้ว่าเกิดอะไรขึ้นกับรหัสของคุณ แต่ฉันได้เพิ่มคำตอบแล้ว วิธีที่แตกต่างอย่างสิ้นเชิงในการบรรลุสิ่งเดียวกันโดยใช้ความพยายามน้อยลง คุณสามารถตรวจสอบได้
Ankush

1
สิ่งนี้ควรยอมรับเป็นคำตอบ! ขอบคุณมากมีประโยชน์มาก !!!
Svetlana Rozhkova

4

จำเป็นต้องตั้งค่าNavigateItemการตรวจสอบเป็นจริงทุกครั้งที่NavigateViewมีการคลิกรายการ

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

เพิ่มNavigationItemSelectedListenerใน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;
  }

ขอบคุณสำหรับความช่วยเหลือของคุณ Vikalp แต่ฉันทำไปแล้ว ( setChecked(true)) ฉันเห็นสีของรายการที่เลือกเปลี่ยนไป แต่ฉันไม่สามารถแก้ไขได้ด้วยตัวเองสีจะเป็นพื้นหลัง navigatioview เวอร์ชันที่อ่อนกว่าเสมอ
Greg

@Greg ตามค่าเริ่มต้นsetChecked(true)ในViewการเปลี่ยนสีพื้นหลังไม่เกินธีมที่อุปกรณ์ที่คุณใช้ หากคุณต้องการเปลี่ยนพื้นหลังของรายการเป็นสีอื่นคุณจำเป็นต้องขยายเลย์เอาต์ของคุณในDrawerLayoutหรือNavigationViewและจัดการด้วยตัวคุณเอง
Vikalp Patel

ขอบคุณอีกครั้งฉันได้พยายามทำตามที่คุณบอก แต่ไม่ประสบความสำเร็จคุณจะมีลิงค์อธิบายวิธีการได้ไหม
Greg

2

นี่คืออีกวิธีหนึ่งในการบรรลุสิ่งนี้:

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

}


สิ่งที่ควรทำของฉันเกี่ยวกับสิ่งที่ฉันต้องการเปลี่ยนสีของรายการเมนูป๊อปอัปที่เลือก แต่ต้องขอบคุณคุณที่ฉันได้รับความคิดที่ดีอย่างหนึ่งจากโซลูชันนี้ของคุณในการเปลี่ยนสีของรายการเมนูที่เลือก ... ดังนั้นให้คุณโหวต !!! และวิธีแก้ปัญหาก็เช่น :: item.setTitle (Html.fromHtml ("<font color = '# ff3824'> การตั้งค่า </font>"));
Tarit Ray

1

นี่คือวิธีที่คุณสามารถทำได้ในวิธีการ onCreate ของกิจกรรมของคุณ:

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

ขั้นตอนที่ 1: สร้างตัวเลือกที่เลือก / ไม่เลือก:

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>

ขั้นตอนที่ 2: ใช้แอตทริบิวต์ xml app:itemTextColorภายในNavigationViewวิดเจ็ตเพื่อเลือกสีข้อความ

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

ขั้นตอนที่ 3:
ด้วยเหตุผลบางประการเมื่อคุณกดรายการจากNavigationViewเมนูจะไม่ถือว่านี่เป็นการตรวจสอบปุ่ม ดังนั้นคุณต้องทำการตรวจสอบรายการที่เลือกด้วยตนเองและล้างรายการที่เลือกไว้ก่อนหน้านี้ ใช้ 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);
    }
}

ขั้นตอนที่ 4:
ในการเปลี่ยนสีไอคอนให้ใช้app:iconTintแอตทริบิวต์ในNavigationViewรายการเมนูและตั้งค่าเป็นตัวเลือกเดียวกัน

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

ผลลัพธ์:

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.