Android NavigationView:如何处理/禁用 header 布局的选择?

Android NavigationView: How do I handle / disable selection of the header layout?

我有一个简单的导航抽屉布局设置。我正在使用设计支持库,所以我有一个导航视图可以滑入支持库的工具栏上方。但是,header 布局响应 UI 中的点击。当我点击 header 布局后方出现涟漪效应。我怎样才能执行以下任一操作:

  1. 一起禁用点击交互? (因此不会产生连锁反应)
  2. 响应点击交互。

我似乎找不到任何关于此的文档。

我注意到了同样的问题。该组件在内部使用了一个 ListView(下面称为 menuView),不幸的是没有禁用 header 选择的选项,因为它是 hard-coded:

this.mHeader = (LinearLayout)this.mLayoutInflater.inflate(layout.design_navigation_item_header, this.mMenuView, false);
this.mMenuView.addHeaderView(this.mHeader);
this.mMenuView.setAdapter(this.mAdapter);
this.mMenuView.setOnItemClickListener(this);

再加上 NavigationView 也有一个图标着色错误(在版本 22.2.0 中),我建议暂时不要使用它。

您可以覆盖布局资源 "design_navigation_item_header" 并添加背景颜色,这样您就不会看到波纹了。

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@android:color/white"
    android:orientation="vertical"
    android:paddingBottom="@dimen/navigation_separator_vertical_padding"/>

如果您想响应点击,您可以按 ID 查找视图并添加一个 OnClickListener。

这可能是解决问题的方法:

View headerView = getLayoutInflater().inflate(R.layout.header_nav, mNavigationView, false);
mNavigationView.addHeaderView(headerView);

//Use this if you don't want the click listener, 
//be sure to use the appropriate background color 
//((ViewGroup) headerView.getParent()).setBackgroundResource(R.color.background_material_light);

//If you want your header to respond to clicks, this should suffice
headerView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        //Open to your implementation
    }
});

根据 的提示,简单地使用 onClick 作品

View headerView = LayoutInflater.from(getActivity()).inflate(R.layout.drawer_header_view, menuItemsNavigationView, false);

headerView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // Consume input from header view. This disables the ripple effect
    }
});

menuItemsNavigationView.addHeaderView(headerView);

我刚刚在我自己的应用程序中处理了这个问题。 NavigationView 是一个包裹在 ListView 周围的 ScrimInsetsFrameLayout,它明确地忽略(丢弃)对列表第一项的点击,即 header。

但是,您可以通过使用自己的包装 NavigationView 的 onItemClickListener 来自行检索它们:

    ListView menuList = (ListView) navigationView.getChildAt(0);
    final AdapterView.OnItemClickListener nativeListener = menuList.getOnItemClickListener();
    menuList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            if (position == 0) {
                drawerLayout.closeDrawer(GravityCompat.START);
                onUserClicked(prefs.getUser());
            }
            nativeListener.onItemClick(parent, view, position, id);
        }
    });

通常我不赞成这种依赖 Android 小部件的内部结构,但在这种情况下,它是支持库,它与您的应用程序一起打包和交付。在较长的 运行 中构建您自己的自定义导航视图可能更好,但有时您需要快速修复!

此页面上的

None 解决方案对我有用,而且可能有充分的理由。正如 BladeCoder 接受的答案所述,侦听器 hard-coded 进入 NavigationDrawer ListView,而 header 视图是 ListView 适配器的第 0 项。如果您想实际禁用它,简单地覆盖膨胀 header 视图的 onClickListener 是行不通的,因为您需要引用 ListView 的适配器项的 onClickListener 而不仅仅是膨胀视图。

下面的解决方案适用于禁止 clicking/tapping header 视图,但它不会禁用可聚焦性(例如使用 d-pad 或键盘)。我似乎还想不通。

    //get the listview within the navigation drawer (0th child)
    ListView menuList = (ListView) mNavigationView.getChildAt(0);

    //get the header view (0th item in listview adapter)
    final View headerView = menuList.getAdapter().getView(0, null, null);

    if (headerView != null) {
        headerView.setEnabled(false); //doesn't work, should
        headerView.setFocusable(false); //doesn't work, should
        headerView.setFocusableInTouchMode(false); //doesn't work, should
        headerView.setClickable(false); //doesn't work, should
        headerView.setOnClickListener(null); //WORKS! works to disallow clicking! is still focusable via keyboard
    }