滚动父级(RecyclerView)时停止父级(NestedScrollview)的滚动

时间:2019-11-30 17:27:33

标签: android android-recyclerview android-scrollview android-nestedscrollview

我需要类似于此实现的行为,但NestedScrollView将是NestedScrollView的父级,而RecyclerView将是NestedScrollView的子级。

例如:https://medium.com/widgetlabs-engineering/scrollable-nestedscrollviews-inside-recyclerview-ca65050d828a

我不确定是否可以实现。尝试在child(RV)滚动时禁用parent(NSV)的功能,但是在子级上滚动会滚动整个视图,包括父级。

5 个答案:

答案 0 :(得分:2)

我已经实施了Marc Knaup解决方案,并且如果NestedScrollView是父级并且结果显示在下面,则所有工作均正确,

enter image description here

顺便说一句,我把我所做的事

CustomRecycleView

package com.example.nested_scroll_test;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import androidx.core.view.NestedScrollingParent;
import androidx.recyclerview.widget.RecyclerView;

public class CustomRecycleView extends RecyclerView implements NestedScrollingParent {
    private View nestedScrollTarget = null;
    private boolean nestedScrollTargetIsBeingDragged = false;
    private boolean nestedScrollTargetWasUnableToScroll = false;
    private boolean skipsTouchInterception = false;


    public CustomRecycleView(Context context) {
        super(context);
    }

    public CustomRecycleView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CustomRecycleView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }


    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        boolean temporarilySkipsInterception = nestedScrollTarget != null;
        if (temporarilySkipsInterception) {
            // If a descendent view is scrolling we set a flag to temporarily skip our onInterceptTouchEvent implementation
            skipsTouchInterception = true;
        }

        // First dispatch, potentially skipping our onInterceptTouchEvent
        boolean handled = super.dispatchTouchEvent(ev);

        if (temporarilySkipsInterception) {
            skipsTouchInterception = false;

            // If the first dispatch yielded no result or we noticed that the descendent view is unable to scroll in the
            // direction the user is scrolling, we dispatch once more but without skipping our onInterceptTouchEvent.
            // Note that RecyclerView automatically cancels active touches of all its descendents once it starts scrolling
            // so we don't have to do that.
            if (!handled || nestedScrollTargetWasUnableToScroll) {
                handled = super.dispatchTouchEvent(ev);
            }
        }

        return handled;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent e) {
        return !skipsTouchInterception && super.onInterceptTouchEvent(e);
    }

    @Override
    public void onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
        if (dyConsumed != 0) {
            // The descendent was actually scrolled, so we won't bother it any longer.
            // It will receive all future events until it finished scrolling.
            nestedScrollTargetIsBeingDragged = true;
            nestedScrollTargetWasUnableToScroll = false;
        } else if (dyConsumed == 0 && dyUnconsumed != 0) {
            // The descendent tried scrolling in response to touch movements but was not able to do so.
            // We remember that in order to allow RecyclerView to take over scrolling.
            nestedScrollTargetWasUnableToScroll = true;
            if (target.getParent() != null)
                target.getParent().requestDisallowInterceptTouchEvent(false);
        }
    }

    @Override
    public void onNestedScrollAccepted(View child, View target, int axes) {
        if (axes != 0 && View.SCROLL_AXIS_VERTICAL != 0) {
            // A descendent started scrolling, so we'll observe it.
            nestedScrollTarget = target;
            nestedScrollTargetIsBeingDragged = false;
            nestedScrollTargetWasUnableToScroll = false;
        }

        super.onNestedScrollAccepted(child, target, axes);
    }

    @Override
    public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
        return nestedScrollAxes != 0 && View.SCROLL_AXIS_VERTICAL != 0;
    }

    @Override
    public void onStopNestedScroll(View child) {
        nestedScrollTarget = null;
        nestedScrollTargetIsBeingDragged = false;
        nestedScrollTargetWasUnableToScroll = false;
    }
}

content_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context=".MainActivity"
    tools:showIn="@layout/activity_main">


    <androidx.core.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorAccent"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="150dp"
                android:background="#FFFFFF"
                android:orientation="vertical">
                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:textAlignment="center"
                    android:text="Top Section"/>
            </LinearLayout>

            <com.example.nested_scroll_test.CustomRecycleView
                android:id="@+id/rw"
                android:layout_width="match_parent"
                android:layout_height="300dp"
                android:background="@color/colorPrimary"
                android:nestedScrollingEnabled="true"
                android:orientation="vertical">

            </com.example.nested_scroll_test.CustomRecycleView>

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="150dp"
                android:background="#FFFFFF"
                android:orientation="vertical" >
                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:textAlignment="center"
                    android:text="Bottom Section"/>
            </LinearLayout>
        </LinearLayout>
    </androidx.core.widget.NestedScrollView>


</androidx.coordinatorlayout.widget.CoordinatorLayout>

RecycleViewItem.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/nsw"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:orientation="vertical">

    <TextView
        android:id="@+id/textview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="2dp"
        android:background="#CCCC"
        android:gravity="center"
        android:nestedScrollingEnabled="false"
        android:orientation="vertical"
        android:padding="2dp"
        android:textColor="#FFFFFF" />
</androidx.core.widget.NestedScrollView>

答案 1 :(得分:0)

将到目前为止您尝试过的全部内容发布出来。

您的xml应该是

<android.support.v4.widget.NestedScrollView
            android:id="@+id/nestedScrollView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:overScrollMode="never">


            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">

              <View > <!-- upper content -->

              <!-- set recycler view with with wrap_content -->
              <android.support.v7.widget.RecyclerView
                    android:id="@+id/recyclerView"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content" />

            </LinearLayout>
      </android.support.v4.widget.NestedScrollView>

在onCreateView()/ onCreate()方法内设置滚动行为。 需要Api 21 +。

    RecyclerView v = (RecyclerView) findViewById(...);
    v.setNestedScrollingEnabled(false);
                   or 
    android:nestedScrollingEnabled="false"  // inside recycler view in xml file

答案 2 :(得分:0)

@Rockin使用overscrollmode bro:)

UserId=1,2,3,Id=1

答案 3 :(得分:0)

这是您想要的外观的演示,位于 MainActivity.xml 文件中:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="MainActivity">

    <android.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:scrollbars="none">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:focusableInTouchMode="true"
            android:orientation="vertical">
            <ImageView
                android:id="@+id/top_seller"
                android:layout_width="match_parent"
                android:layout_height="200sp"
                android:background="@color/colorAccent"
                android:contentDescription="@string/app_name"
                android:adjustViewBounds="true"
                android:src="@drawable/background"
                android:scaleType="fitXY"/>
            <ImageView
                android:id="@+id/top_seller1"
                android:layout_width="match_parent"
                android:layout_height="200sp"
                android:background="@color/colorAccent"
                android:contentDescription="@string/app_name"
                android:adjustViewBounds="true"
                android:src="@drawable/background"
                android:scaleType="fitXY"/>
            <android.support.v7.widget.RecyclerView
                android:id="@+id/product_list"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical"
                android:scrollbars="none" />
            <ImageView
                android:id="@+id/top_seller2"
                android:layout_width="match_parent"
                android:layout_height="200sp"
                android:background="@color/colorAccent"
                android:contentDescription="@string/app_name"
                android:adjustViewBounds="true"
                android:src="@drawable/background"
                android:scaleType="fitXY"/>
            <ImageView
                android:id="@+id/top_seller3"
                android:layout_width="match_parent"
                android:layout_height="200sp"
                android:background="@color/colorAccent"
                android:contentDescription="@string/app_name"
                android:adjustViewBounds="true"
                android:src="@drawable/background"
                android:scaleType="fitXY"/>
        </LinearLayout>
    </android.support.v4.widget.NestedScrollView>
</LinearLayout>

在您的 MainActivity.java onCreate方法中:

   RecyclerView bestRecyclerView = findViewById(R.id.product_list);
   GridLayoutManager mGrid = new GridLayoutManager(this, 2);
   bestRecyclerView.setLayoutManager(mGrid);
   bestRecyclerView.setHasFixedSize(true);
   bestRecyclerView.setNestedScrollingEnabled(false);
   // Create ProductAdapter for  RecyclerView data
   ProductAdapter mAdapter = new ProductAdapter(MainActivity4.this,getProductTestData());
   bestRecyclerView.setAdapter(mAdapter);

enter image description here

我希望它能帮助您...!

答案 4 :(得分:-1)

您是否尝试将RV子类化并覆盖onInterceptTouchEvent?

#Include conf/pagespeed.conf
#Include conf/pagespeed_libraries.conf