12

I need behavior similar to this implementation But NestedScrollView would be the parent and RecyclerView would be the child of would NestedScrollView .

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

I am not sure whether it can be achieved.Tried disabling the of parent(NSV) while child(RV)is scrolling But scroll on child scrolls the entire view including parent.

1
  • did you get the answer as per medium it can achievable, can you please share some code Commented Dec 3, 2019 at 10:13

6 Answers 6

3
+175

I'v implemented Marc Knaup solution and all works correct event if NestedScrollView would be the parent and the result was shown below

enter image description here

btw, i put what i'v done

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> 
Sign up to request clarification or add additional context in comments.

Comments

0

@Rockin use overscrollmode bro:)

 <androidx.core.widget.NestedScrollView android:layout_width="match_parent" android:fillViewport="true" android:overScrollMode="always" android:layout_height="match_parent"> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/color_white" android:orientation="vertical"> <androidx.recyclerview.widget.RecyclerView android:id="@+id/activity_insight_recyclerview_list" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginTop="@dimen/_20sdp" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" tools:listitem="@layout/raw_insight" /> 

2 Comments

scrolling behaviour mentioned in this medium.com/widgetlabs-engineering/… cannot be achieved by using overscroll mode .
@Rockin you have to give android:layout_height="match_parent" and it's defiantly work i am using this in my code.
0

post entire thing what you have tried so far.

your xml should be ,

<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> 

set scrolling behaviour inside onCreateView() / onCreate() method. requires Api 21+ .

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

2 Comments

scrolling behaviour mentioned in this medium.com/widgetlabs-engineering/… cannot be achieved by using overscroll mode .
this is not a solution because android:nestedScrollingEnabled="false" freeze recycleview.
0

This is demo for what you want look, In MainActivity.xml file :

<?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> 

In your MainActivity.java class onCreate method:

 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

I hope It'll help you...!

2 Comments

Have you find your answers or need a help?
Is it helpful for you?
0

In general simple trick works for me. When attaching OnTouchListener to child View, in onTouch() just disable touch interrupts. Something like this:

 RecyclerView rv = findViewById(...); rv.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { ... v.getParent().requestDisallowInterceptTouchEvent(true); 

Comments

-1

Have you try subclass the RV and override onInterceptTouchEvent?

override fun onInterceptTouchEvent(event: MotionEvent?): Boolean { when (event!!.action and MotionEvent.ACTION_MASK) { MotionEvent.ACTION_DOWN -> { // WE INTERACT WITH THIS RV. PREVENT PARENT TO INTERCEPT parent.requestDisallowInterceptTouchEvent(true) } MotionEvent.ACTION_MOVE, MotionEvent.ACTION_CANCEL, MotionEvent.ACTION_UP -> { // THIS SEEMS LIKE IT WILL HAVE "DEFAULT" BEHAVIOUR BUT SINCE WE CURRENTLY DRAGGING THE RV THEN IT WONT SCROLL THE PARENT parent.requestDisallowInterceptTouchEvent(false) } } return false } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.