27

I have a layout like that:

<NestedScrollView>
     <RecyclerView> // vertical recycler view
          <RecyclerView/>  // horizontal recycler view
          <RecyclerView/>
          <RecyclerView/>
          ...
     <RecyclerView>
</NestedScrollView>

The result looks like Google play store: enter image description here

And I disabled NestedScrolling in horizontal Recycler view:

horizontalRecyclerView.setHasFixedSize(true);
horizontalRecyclerView.setNestedScrollingEnabled(false);

My problem:

The vertical recyclerview does not scroll fling, whenever ACTION_UP happen, the vertical recyclerview also stop scrolling.

How can I nest vertical recyclerview inside nestedscrollview, and horizontal recyclerview inside vertical recyclerview like Playstore and keep the scroll smooth.

Solved:

Using custom nested scroll view of @vrund purohit (code below), and disabled nestedscroll both vertical and horizontal recyclerview:

verticalRecyclerView.setNestedScrollingEnabled(false);
... add each horizontal recyclerviews:
horizontalRecyclerView.setNestedScrollingEnabled(false);
Khang .NT
  • 1,504
  • 6
  • 24
  • 46
  • https://stackoverflow.com/questions/27083091/recyclerview-inside-scrollview-is-not-working/45466603#45466603 Check this link.. – maruti060385 Aug 04 '17 at 15:14

5 Answers5

52

Use below code for smooth scroll:

ViewCompat.setNestedScrollingEnabled(recyclerView, false);
Kuldeep Sakhiya
  • 3,172
  • 1
  • 18
  • 17
11

Add this in your RecyclerView xml:

android:nestedScrollingEnabled="false"
jbc25
  • 1,192
  • 2
  • 14
  • 20
  • This only works for API level 21 and above for below API level 21 see Kuldeeps answer. – Clive Jefferies Sep 21 '17 at 08:42
  • 1
    If you're using databinding in your layout you can also create a bindingadapter: @BindingAdapter("nestedScrollingEnabled") public static void setNestedScrollingEnabled(final View view, final boolean value) { ViewCompat.setNestedScrollingEnabled(view, value); } and then add to layouts with app:nestedScrollingEnabled="@{false}" – Barry Irvine Jan 22 '18 at 11:36
9

I had this same problem and I solved this issue by customizing NeatedScrollView.

Here is the class for that.

MyNestedScrollView

public class MyNestedScrollView extends NestedScrollView {
    @SuppressWarnings("unused")
    private int slop;
    @SuppressWarnings("unused")
    private float mInitialMotionX;
    @SuppressWarnings("unused")
    private float mInitialMotionY;
    public MyNestedScrollView(Context context) {
        super(context);
        init(context);
    }
    private void init(Context context) {
        ViewConfiguration config = ViewConfiguration.get(context);
        slop = config.getScaledEdgeSlop();
    }
    public MyNestedScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }
    public MyNestedScrollView(Context context, AttributeSet attrs,
            int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }
    private float xDistance, yDistance, lastX, lastY;
    @SuppressWarnings("unused")
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        final float x = ev.getX();
        final float y = ev.getY();
        switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN:
            xDistance = yDistance = 0f;
            lastX = ev.getX();
            lastY = ev.getY();
            // This is very important line that fixes
            computeScroll();
            break;
        case MotionEvent.ACTION_MOVE:
            final float curX = ev.getX();
            final float curY = ev.getY();
            xDistance += Math.abs(curX - lastX);
            yDistance += Math.abs(curY - lastY);
            lastX = curX;
            lastY = curY;
            if (xDistance > yDistance) {
                return false;
            }
        }
        return super.onInterceptTouchEvent(ev);
    }
    public interface OnScrollChangedListener {
        void onScrollChanged(NestedScrollView who, int l, int t, int oldl,
                int oldt);
    }
    private OnScrollChangedListener mOnScrollChangedListener;
    public void setOnScrollChangedListener(OnScrollChangedListener listener) {
        mOnScrollChangedListener = listener;
    }
    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        if (mOnScrollChangedListener != null) {
            mOnScrollChangedListener.onScrollChanged(this, l, t, oldl, oldt);
        }
    }
}

Happy coding.

V-rund Puro-hit
  • 5,518
  • 9
  • 31
  • 50
  • https://stackoverflow.com/questions/27083091/recyclerview-inside-scrollview-is-not-working/45466603#45466603 – maruti060385 Aug 04 '17 at 15:14
  • 1
    Is there any advantage over the simple answer [below](https://stackoverflow.com/a/43536382/905686)? If not, consider accepting the simpler one. – user905686 Aug 23 '17 at 11:18
4

[RESOLVED] I have same issue with Horizontal recycleview. Change Gradle repo for recycleview

compile 'com.android.support:recyclerview-v7:23.2.1' Write this: linearLayoutManager.setAutoMeasureEnabled(true);

Fixed bugs related to various measure-spec methods in update

Check http://developer.android.com/intl/es/tools/support-library/features.html#v7-recyclerview

I have found issue with 23.2.1 library: When item is match_parent recycle view fill full item to view, please always go with min height or "wrap_content".

Thanks

Amit
  • 409
  • 1
  • 5
  • 12
1

I've solved the issue by using below code:

        myRecyclerView.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false){
        @Override
        public boolean canScrollHorizontally() {
            return true;
        }

        @Override
        public boolean canScrollVertically() {
            return true;
        }
    });
Waqar UlHaq
  • 6,144
  • 2
  • 34
  • 42