Android:itemBackground

时间:2016-09-09 00:39:26

标签: android android-layout 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 个答案:

答案 0 :(得分:2)

搜索结果

Change the color of a checked menu item in a navigation drawer

但我不认为它会起作用,因为在源代码中,它从未设置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;
    }
});

注意

  1. 因为ViewHolder.itemView是一个没有setChecked方法的视图,所以我们使用选中而不是选中;所以你需要更改你的background drawable xml,只需将android:state_checked更改为android:state_selected
  2. 即可
  3. 使用反射不是一个好主意,我建议您编写自己的布局来满足您的需求,而不是使用NavigationView。