Android: селектор NavigationView для элемента фона
У меня есть NavigationView, со многими элементами в нем.
Я пытаюсь изменить фон выбранного (отмеченного) элемента. У меня есть селектор, который изменяет itemTextColor, и это прекрасно работает.
У меня есть ресурс для рисования:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="@color/selected_item_accent"/>
</shape>
И мой селектор:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/nav_view_background" android:state_checked="true" />
<item android:drawable="@drawable/nav_view_background" android:state_pressed="true" />
<item android:drawable="@android:color/transparent" />
</selector>
И, наконец, NavigationView
<android.support.design.widget.NavigationView
android:id="@+id/navView"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="@color/window_background"
app:itemTextColor="@drawable/selector_nav_view_text"
app:itemBackground="@drawable/selector_nav_view_background"
app:headerLayout="@layout/app_nav_header" />
Нажатое состояние работает как положено, но фон выбранного элемента не изменяется.
Мне интересно, что я здесь делаю не так. Благодарю.
1 ответ
Результат поиска
Изменить цвет отмеченного пункта меню в панели навигации
НО я не думаю, что это будет работать, потому что в исходном коде он никогда не устанавливает реальный элемент RecyclerView (не пункт меню) проверено. Это означает, что при нажатии на пункт, проверяется только пункт меню. Так что, конечно, фон не изменится.
Временное решение
Кажется, что NavigationView не предназначен для того, что вы хотите. Дизайнер может подумать, что когда пользователь щелкает элемент в NavigationView, он должен быть закрыт, и приложение будет перемещать пользователя на другую страницу. Так setChecked()
не нужен;
НО есть обходной путь с использованием отражения. основной код похож
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_menu_item_1:
// find out the position of the menu item in Adapter
// in my test demo, positionInAdapter = positionInMenu + 2
int positionInAdapter = NUMBER;
try {
Field presenterField = mNavigationSpan.getClass().getDeclaredField("mPresenter");
presenterField.setAccessible(true);
// get NavigationMenuPresenter from your NavigationView
NavigationMenuPresenter presenter = (NavigationMenuPresenter) presenterField.get(mNavigationSpan);
Field menuViewField = presenter.getClass().getDeclaredField("mMenuView");
menuViewField.setAccessible(true);
// get NavigationMenuView from NavigationMenuPresenter, it is a RecyclerView which contains the real items user seen
NavigationMenuView menuView = (NavigationMenuView) menuViewField.get(presenter);
// using RecyclerView.findViewHolderForAdapterPosition() to get the ViewHolder, then you can get the itemView
menuView.findViewHolderForAdapterPosition(positionInAdapter).itemView.setSelected(true);
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
break;
}
return false;
}
});
Заметка
- поскольку ViewHolder.itemView является представлением, которое не имеет
setChecked
метод, поэтому мы используем выбранный вместо отмеченного; так что вам нужно изменить свой фон рисования XML, просто изменитеandroid:state_checked
вandroid:state_selected
- использование отражения НЕ является хорошей идеей, я рекомендую вам написать свой собственный макет, чтобы удовлетворить ваши потребности вместо использования NavigationView.