Vertical ViewPager2 with RecyclerView Scrolling Issue

痞子三分冷 提交于 2020-12-10 07:37:56

问题


I'm using a ViewPager2 with two fragments in a vertical orientation. When the user swipes down to the second fragment, there is a RecyclerView that scrolls content in the same vertical direction.

The issue is that when I scroll the contents of the RecyclerView, sometimes the ViewPager2 catches the scroll events and sometimes the RecyclerView catches the scroll events.

I would like it so that when the user is scrolling to the top of the RecyclerView, the ViewPager only swipes back up to the first fragment when the user has reached the top of the contents in the RecyclerView.

I've tried using recyclerView.isNestedScrollingEnabled = false without much luck. I also tried putting the RecyclerView into a NestedScrollView, but that is not recommended because the RecyclerView then creates every single ViewHolder it needs for the dataset and that is obviously not efficient.


回答1:


So...I was able to figure it out by just reading some documentation 😅. I'll post the answer here so that it helps anyone else having a similar issue:

Since ViewPager2 does not supported nested scroll views very well, unlike NestedScrollView, we need to wrap our nested scrollview with a custom wrapper in our layout to be able to handle the touch and swipe events that are getting intercepted by our nested scroll views parent. In our case, the child would be the RecyclerView and the parent would be the ViewPager2.

You can find the wrapper class here. Simply add it to your project and then wrap your scrollable view in it, similar to below:

    <NestedScrollableHost
            android:layout_width="match_parent"
            android:layout_height="match_parent">

        <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/my_recycler_view"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical" />

    </NestedScrollableHost>

There are a couple things to note here: The documentation says that this solution will not work for scrollable views that are within other scrollable views within the ViewPager. This solution only works for immediate scroll views of the ViewPager.

Another note is that the wrapper class uses the requestDisallowInterceptTouchEvent() to make sure that the child scrollable view tells the parent not to scroll if the child needs to scroll instead.




回答2:


The best solution till i get is use gestureDetector.SimpleOnGestureListener inside on recyclerView.addOnItemTouchListener(this).

Step-1: In OnCreate() method

gestureDetector = new GestureDetector(getActivity(), new GestureListener());

Step-2: Implement recyclerView addonitemtouchlistenr method-

recyclerView.addOnItemTouchListener(this);

Step-3: Create class GestureListener that extends GestureDetector.SimpleOnGestureListener.

public class GestureListener extends GestureDetector.SimpleOnGestureListener {
    private final int Y_BUFFER = 10;

    @Override
    public boolean onDown(MotionEvent e) {
        // Prevent ViewPager from intercepting touch events as soon as a DOWN is detected.
        // If we don't do this the next MOVE event may trigger the ViewPager to switch
        // tabs before this view can intercept the event.
        Log.d("vp", "true1");
        recyclerView.getParent().requestDisallowInterceptTouchEvent(true);
        return super.onDown(e);
    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        if (Math.abs(distanceX) > Math.abs(distanceY)) {
            Log.d("vp2", "true");
            // Detected a horizontal scroll, allow the viewpager from switching tabs
            recyclerView.getParent().requestDisallowInterceptTouchEvent(false);
        } else if (Math.abs(distanceY) > Y_BUFFER) {
            // Detected a vertical scroll prevent the viewpager from switching tabs
            Log.d("vp3", "false");
            recyclerView.getParent().requestDisallowInterceptTouchEvent(true);
        }
        return super.onScroll(e1, e2, distanceX, distanceY);
    }
}

Step-4: call gestureDetector.onTouchEvent(e) from onInterceptTouchEvent().

@Override
public boolean onInterceptTouchEvent(@NonNull RecyclerView rv, @NonNull MotionEvent e) {
    gestureDetector.onTouchEvent(e);
    return false;
}


来源:https://stackoverflow.com/questions/60640368/vertical-viewpager2-with-recyclerview-scrolling-issue

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!