Изменение цвета фона в BottomNavigationView

Я реализовал BottomNavigationView, который доступен из новой библиотеки поддержки 25.0.0. Вот мой код для этого

<android.support.design.widget.BottomNavigationView
    android:id="@+id/bottom_navigation"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    app:itemBackground="@color/colorPrimary"
    app:itemIconTint="@drawable/text"
    app:itemTextColor="@drawable/text"
    app:menu="@menu/bottom_navigation_main" />

И text.xml drawable

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

С помощью этого кода я могу изменить цвет текста при нажатии элемента меню, но когда я применяю то же самое к app:itemBackground, он показывает ошибку <item> tag requires a 'drawable' attribute or child tag defining a drawable.

Это то, что я пробовал для app:itemBackground

app:itemBackground="@drawable/text"

Итак, мой вопрос в том, как изменить цвет фона выбранного пункта меню?

Ответы

Ответ 1

нашел ответ на этот средний пост

  • Нам нужно использовать android:state_checked вместо android:state_enabled
  • внутри onNavigationItemSelected вам нужно использовать return true вместо return false.

и для установки фона мы не можем использовать android:color в <item>, нам нужно использовать android:drawable

Итак, вот как выглядит файл xml, когда вы устанавливаете его для app:itemTextColor и app:itemIconTint

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

и установить селектор app:itemBackground

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

Здесь banner_white и banner_green являются pngs.

Ответ 2

Я столкнулся с аналогичной проблемой с OP, но немного по-другому. Если вы поместите sth как @color/color_selector в BottomNavigationView app:itemBackground="___". Это приведет к тому, что представление будет скрыто в панели дизайна, а приложение будет раздавлено при запуске. Хотя он отлично работает, если вы просто установите его на постоянный цвет, например @color/black.

Для более подробного объяснения я перекопал ссылку на android api. Теперь я думаю, что нашел ответ, который может разумно решить эту проблему. (Может быть неточным.)

Проблема в том, что то, что вы предоставляете, НЕ ТОЧНО, о чем они просили.

app:itemIconTint и app:itemTextColor запросить шестнадцатеричный цвет, а app:itemBackground запрашивает буквально Drawable. Элементы <color>, которые мы пишем в colors.xml, ColorDrawable. Он получен из Drawable, чтобы он мог загружать все три атрибута.

Однако, когда вы меняете его на использование селектора, все становится по-другому. Оба цвета в шестнадцатеричной форме и с возможностью рисования имеют соответствующий селектор. Селектор действует как ресурс, который вы вставляете, но результат не является исходным. Это больше похоже на универсальную упаковку. Вы не можете передать шестнадцатеричный цвет атрибуту, которому требуется Drawable.

Селектор цвета на самом деле является ColorStateList, имеет шестнадцатеричный цвет, находится в res/color. Вы можете использовать только атрибут android:color в этом файле. он выдает сообщение об ошибке, если вы пишете android:drawable.
Выбираемый селектор StateListDrawable, предоставляет Drawable, находится в res/drawable. Здесь вы должны написать android:drawable, но нет ошибки, если вы напишете android:color.

Однако android:color предоставляет только шестнадцатеричный цвет, который не может быть распознан как Drawable, тогда как app:itemBackground требует Drawable, поэтому приложение обречено. (прямая причина)

Оба атрибута (android:color и android:drawable) принимают ColorDrawable, здесь он работает так же, как при установке постоянного цвета.

Решение (и практика):

  • Используйте (и только) android:drawable в res/drawable/drawable_selector.xml. Пример:

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:drawable="@color/colorAccent" android:state_checked="true" />
        <item android:drawable="@color/colorAccentDark" />
    </selector>
    
  • Используйте res/color/color_selector.xml, когда для этого требуется шестнадцатеричный цвет (во избежание путаницы). Пример:

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:color="@android:color/white" android:state_checked="true"/>
        <item android:color="@color/colorPrimary" />
    </selector>
    
  • Предоставьте app:itemBackground с возможностью рисования. Пример:

    <android.support.design.widget.BottomNavigationView
        ...
        app:itemBackground="@drawable/drawable_selector"
        app:itemIconTint="@color/color_selector"
        app:itemTextColor="@color/color_selector"
        ... />
    

(Стоит отметить, что если вы используете Android Studio, функция автозаполнения скажет вам, какие атрибуты являются законными и доступными, и не предлагает вам android:color в селекторе под res/drawable!)

Ответ 3

Попробуйте, это пример кода для выбора пункта меню навигации. надеюсь, что это поможет вам.

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

Альтернативное решение:

Сделайте выделенный файл 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>

Наконец, добавьте приложение: 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.

Попробуйте это.