Nested RecyclerView with Horizontal Scroll

I'm trying to implement nested RecyclerViews with 3 layers. The 1st RecyclerView (parent) view is set to scroll vertically. The 2nd RecyclerView (child of the 1st) view is set to scroll horizontally. The 3rd RecyclerView (child of the 2nd) view is also set to scroll horizontally.

To visualize:

-> RecyclerView with vertical scroll
--> RecyclerView with horizontal scroll
---> RecyclerView with horizontal scroll

Now, the problem is I can't make the 3rd horizontal RecyclerView scroll horizontally. I think the problem is the device is prioritising the horizontal scroll of the 2nd RecyclerView.

Can you help me solve this issue?

This is the snippet code for the layout of the 1st one with vertical scrolling:

<android.support.v4.widget.NestedScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent">

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

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

This is for the 2nd one with horizontal scrolling:

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

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

</LinearLayout>

This is for the last one with horizontal scrolling:

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>

I already tried intercepting the touch with onIntercept...() to cancel the scrolling of the 2nd RecyclerView while the 3rd is being touched.

Upvotes: 0

Views: 604

Answers (1)

Ganesh Pokale
Ganesh Pokale

Reputation: 1594

public class NestedScrollViewHome  extends NestedScrollView {
    @SuppressWarnings("unused")
    private int slop;
    @SuppressWarnings("unused")
    private float mInitialMotionX;
    @SuppressWarnings("unused")
    private float mInitialMotionY;
    public NestedScrollViewHome(Context context) {
        super(context);
        init(context);
    }
    private void init(Context context) {
        ViewConfiguration config = ViewConfiguration.get(context);
        slop = config.getScaledEdgeSlop();
    }
    public NestedScrollViewHome(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }
    public NestedScrollViewHome(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);
        }
    }
}

Upvotes: 0

Related Questions