Search code examples
androidandroid-coordinatorlayout

CoordinatorLayout: How can I prevent scroll events from reaching RecyclerView?


I have a layout consisting of a CoordinatorLayout parent with a NestedScrollView containing a ViewPager, which contains a RecyclerView:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.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"
    tools:context="com.example.snap.MainActivity"
    tools:layout_editor_absoluteX="8dp"
    tools:layout_editor_absoluteY="8dp">

    <android.support.v4.widget.NestedScrollView
        android:id="@+id/nested_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fillViewport="true">

        <android.support.constraint.ConstraintLayout
            android:id="@+id/scroll_container"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <LinearLayout
                android:id="@+id/linearLayout3"
                android:layout_width="match_parent"
                android:layout_height="40dp"
                android:orientation="vertical"
                android:layout_gravity="top"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintLeft_toLeftOf="parent">

            </LinearLayout>

            </LinearLayout>

            <android.support.v4.view.ViewPager
                android:id="@+id/id_viewpager_photosvideos_albums"
                android:layout_width="match_parent"
                android:layout_height="1000dp"
                app:layout_constraintHorizontal_bias="0.0"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/linearLayout1">

                <android.support.design.widget.TabLayout
                    android:id="@+id/id_tab_photosvideos_albums"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_gravity="top">

                    <android.support.design.widget.TabItem
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content" />

                    <android.support.design.widget.TabItem
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content" />

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


            </android.support.v4.view.ViewPager>


        </android.support.constraint.ConstraintLayout>

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

    </LinearLayout>

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

I want to achieve the following:

I want to intercept(prevent) the scroll events from reaching RecyclerView until a certain threshold condition is reached. post which, RecyclerView shall start intercepting scroll events normally.

How can I achieve this?


Note: I have tried looking into Behavior.onNestedScroll() but that doesn't seem to do the trick.


Solution

  • Finally found the answer -

    By consuming them like this(in CoordinatorLayout.Behavior):

    @Override
        public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, NestedScrollView child, View directTargetChild, View target, int nestedScrollAxes) {
            return (nestedScrollAxes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0;
        }
    
        @Override
        public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, NestedScrollView child, View target, int dx, int dy, int[] consumed) {
    
            int mCurrentScrollOffset = target.getScrollY();
    
            if(mCurrentScrollOffset <= thresholdScrollDistance){
                consumed[1] = dy;
                child.scrollBy(0, dy);
            }
        }
    

    Why?

    Because, consumed[i] is an out variable storing x and y scroll unconsumed values for consumption.