user246392
user246392

Reputation: 3017

Parent RecyclerView picks up gestures that were intended to be for the nested RecyclerView

I have a vertical RecyclerView and a nested horizontal RecyclerView as one of its children. The inner view is used as an image carousel with a PagerSnapHelper. I'm getting a less than ideal behavior when I try to scroll the inner view horizontally. Sometimes, the parent view picks up the gesture and scrolls vertically even though my intention was to scroll the inner view horizontally. Is there a way to configure the default scroll detector such that horizontal scrolling is smoother?

Upvotes: 5

Views: 1340

Answers (2)

titanwalking
titanwalking

Reputation: 49

below approach is trying to disable touch events for parent recyclerview when touching to nested recyclerview.

    nestedRecyclerView.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch (View v, MotionEvent event){
    int action = event.getAction();
    switch (action) {
        case MotionEvent.ACTION_DOWN:
            // Disallow parent to intercept touch events.
            v.getParent().requestDisallowInterceptTouchEvent(true);
            break;

        case MotionEvent.ACTION_UP:
            // Allow parent to intercept touch events.
            v.getParent().requestDisallowInterceptTouchEvent(false);
            break;
    }

    // Handle inner(child) touch events.
    v.onTouchEvent(event);
    return true;
}
});

Upvotes: 1

Rinat Diushenov
Rinat Diushenov

Reputation: 1245

Can you try using this RecyclerView with overriden method as a parent RecyclerView:

public class CustomRecyclerView extends RecyclerView {

    private int mTouchSlop;
    private float mPrevX;

    public CustomRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent e) {
        switch (e.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mPrevX = MotionEvent.obtain(e).getX();
                break;

            case MotionEvent.ACTION_MOVE:
                final float eventX = e.getX();
                float xDiff = Math.abs(eventX - mPrevX);

                if (xDiff > mTouchSlop) {
                    return false;
                }
        }

        return super.onInterceptTouchEvent(e);
    }
}

example in xml

<com.example.stackoverflow.CustomRecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

Upvotes: 4

Related Questions