首页 > 解决方案 > 在 Navigation Drawer Header 中拦截触摸事件以允许 RecyclerView 滚动?

问题描述

我正在尝试将一个可变的用户名列表添加到导航抽屉的标题中。一旦 recyclerview 的高度超过标题的给定尺寸,我就无法访问 recyclerview 中的隐藏项目。我想我需要从 DrawerLayout 拦截触摸事件并将它们传递给标题和回收器视图以允许它滚动,但我不确定我将如何去做。

这是主要活动 xml 文件:

<android.support.v4.widget.DrawerLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">

<include
    layout="@layout/app_bar_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />



<android.support.design.widget.NavigationView
    android:id="@+id/nav_view"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:fitsSystemWindows="true"
    app:headerLayout="@layout/nav_header_main"
    app:menu="@menu/activity_main_drawer" />

</android.support.v4.widget.DrawerLayout>

这是 nav_header_main.xml 文件:

<LinearLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="@dimen/nav_header_height"
android:background="@drawable/side_nav_bar"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:id="@+id/addUserLayout"
android:theme="@style/ThemeOverlay.AppCompat.Dark">

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingTop="10dp"
    android:textSize="22sp"
    android:text="@string/add_user"
    android:id="@+id/navbarAddUser"/>


<android.support.v7.widget.RecyclerView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/rvUsers"/>


</LinearLayout>

我试图构建一个 CustomDrawerLayout 类来将标题中的触摸事件传递给 headerview,但它没有完成我想要的。这是该类的 onInterceptTouchEvent 方法:

    @Override
public boolean onInterceptTouchEvent(MotionEvent ev) {


    NavigationView navigationView = (NavigationView) getChildAt(1);

    View headerView = navigationView.getHeaderView(0);

    final int action = ev.getAction();

    switch(action) {
        case MotionEvent.ACTION_MOVE :
            //if mouse is dragged we dont intercept
            if(ev.getY() < headerView.getHeight() + headerView.getY() &&
                    ev.getX() < headerView.getWidth() + headerView.getX() &&
                    ev.getX() > headerView.getX() &&
                    ev.getY() > headerView.getY()) {
                isScrolling = true;
                Log.d(TAG_DRAWERLAYOUT, "scrolling");
                return false;
            }
            if(isScrolling) {
                Log.d(TAG_DRAWERLAYOUT, "scrolling outside of header");
                return false;
            }
            return true;
        case MotionEvent.ACTION_UP:
            isScrolling = false;
            return super.onInterceptTouchEvent(ev);
    }

    return super.onInterceptTouchEvent(ev);
}

任何帮助,将不胜感激!我对 Android 开发还很陌生,显然还有很多东西要学。

标签: androidandroid-layoutandroid-recyclerviewandroid-touch-event

解决方案


多考虑一下这个问题,我就找到了一个体面的解决方法。我没有将导航栏标题作为单独的布局文件,而是将我想要的项目包含在标题中作为 NavigationView 主体的成员。然后为了移动 NavigationDrawer 的菜单内容,我使用了具有透明背景的约束布局,并且与 Navigation View 主体中的项目高度相等。

活动主.xml:

<android.support.v4.widget.DrawerLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">

<include
    layout="@layout/app_bar_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />


<android.support.design.widget.NavigationView
    android:id="@+id/nav_view"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:fitsSystemWindows="true"
    app:menu="@menu/activity_main_drawer"
    app:headerLayout="@layout/nav_header_blank">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <include layout="@layout/nav_header_main"/>

    <android.support.v7.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="@dimen/nav_header_bottom_height"
        android:id="@+id/rvUsers"/>
    </LinearLayout>

</android.support.design.widget.NavigationView>

</android.support.v4.widget.DrawerLayout>

nav_header_main.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="@dimen/nav_header_top_height"
android:background="@drawable/side_nav_bar"
android:orientation="vertical"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:id="@+id/addUserLayout"
android:theme="@style/ThemeOverlay.AppCompat.Dark">

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingTop="16dp"
    android:textSize="22sp"
    android:text="@string/add_user"
    android:id="@+id/navbarAddUser"/>

</LinearLayout>

nav_header_main.xml:

<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="176dp"
    android:background="#00FFFFFF">

</android.support.constraint.ConstraintLayout>

推荐阅读