RecyclerView无限滚动在ViewPager2中不起作用

Posted

技术标签:

【中文标题】RecyclerView无限滚动在ViewPager2中不起作用【英文标题】:RecyclerView infinite scroll not working inside ViewPager2 【发布时间】:2022-01-02 13:46:10 【问题描述】:

我有一个水平的ViewPager2。在视图寻呼机的第二张幻灯片上,我有一个实现了无限滚动的RecyclerView。我用EndlessRecyclerViewScrollListener实现无限滚动。

但是,当向下滚动此RecyclerView 时,它不会触发无限滚动。永远不会调用无限滚动的第 2 页,只有第 1 页。

这是我的班级ViewPager2

public class BaseBottomNavigationViewActivity extends BaseActivity implements BottomNavigationView.OnNavigationItemSelectedListener 

    // The number of pages in the bottom navigation view
    private static final int NUM_PAGES = 5;

    // The view pager
    private ViewPager2 viewPager;

    // The pager adapter
    private FragmentStateAdapter pagerAdapter;

    // The bottom navigation view
    private BottomNavigationView bottomNavigationView;

    private NewPostBottomSheetDialogFragment newPostModalDialog;

    private RelativeLayout newPostButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);

        viewPager = findViewById(R.id.view_pager);
        bottomNavigationView = findViewById(R.id.bottom_navigation_view);

        // The number of screens to keep in memory
        viewPager.setOffscreenPageLimit(5);

        // Disable swiping in the view pager
        viewPager.setUserInputEnabled(false);

        // Set the pager adapter
        pagerAdapter = new BottomNavigationViewPagerAdapter(this);
        viewPager.setAdapter(pagerAdapter);

        // Register the item selected listener
        bottomNavigationView.setOnNavigationItemSelectedListener(this);

        // Set default selection (home)
        bottomNavigationView.setSelectedItemId(R.id.action_first);
    

    @Override
    protected int getLayoutResource() 
        return R.layout.activity_base_bottom_navigation_view;
    

    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) 
        switch (item.getItemId()) 
            case R.id.action_first:
                viewPager.setCurrentItem(0, false);
                break;
            case R.id.action_second:
                viewPager.setCurrentItem(1, false);
                break;
            case R.id.action_third:
                return false;
            case R.id.action_fourth:
                viewPager.setCurrentItem(3, false);
                break;
            case R.id.action_fifth:
                viewPager.setCurrentItem(4, false);
                break;
            default:
                break;
        

        return true;
    

    private static class BottomNavigationViewPagerAdapter extends FragmentStateAdapter 
        public BottomNavigationViewPagerAdapter(FragmentActivity fa) 
            super(fa);
        

        @Override
        public Fragment createFragment(int position) 
            switch (position) 
                case 0:
                    return new FirstPageFragment();
                case 1:
                    return new SecondPageFragment();
                case 2:
                    return new ThirdPageFragment();
                case 3:
                    return new FourthPageFragment();
                case 4:
                    return new FifthPageFragment();
            

            return null;
        

        @Override
        public int getItemCount() 
            return NUM_PAGES;
        
    


这是ViewPager2中第二页的类:

public class SecondPageFragment extends Fragment 

    private MyAdapter myAdapter;

    private LinearLayoutManager layoutManager;

    private RecyclerView recyclerView;

    private EndlessRecyclerViewScrollListener scrollListener;

    private List<Object> objects = new ArrayList<>();

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) 
        return inflater.inflate(R.layout.fragment_page_two, parent, false);
    

    @Override
    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) 
        super.onViewCreated(view, savedInstanceState);

        recyclerView = view.findViewById(R.id.recycler_view);

        layoutManager = new LinearLayoutManager(getContext());
        recyclerView.setLayoutManager(layoutManager);

        myAdapter = new MyAdapter(getContext(), layoutManager, objects);
        recyclerView.setAdapter(myAdapter);

        scrollListener = new EndlessRecyclerViewScrollListener(layoutManager) 
            @Override
            public void onLoadMore(int page, int totalItemsCount, RecyclerView view) 
                getData(page);
            
        ;
        recyclerView.addOnScrollListener(scrollListener);
    

    private void getData(final int page) 
        // Here I call the API to fetch the data and add them to the objects list
    

为什么在这种情况下滚动时它不为 RecyclerView 调用第 2 页,我该怎么做才能解决它?

谢谢!

【问题讨论】:

可能需要禁用ViewPager2的内部RecyclerView的嵌套滚动;请看here 【参考方案1】:

您可能有兴趣检查您对 ViewPager2 的约束,因为它托管包含 RecyclerView 的片段 - 以及此特定片段的整个结构(在您的 XML 布局中)。

由于两者都是可滚动的,布局层次结构的layout_heightlayout_width对触发recyclerView的事件有很大影响,其中一些可能永远不会到达事件监听器。

在从 ViewPager 迁移的官方文档中,有一个关于支持嵌套滚动的小说明here

在滚动视图与包含它的 ViewPager2 对象具有相同方向的情况下,ViewPager2 本身不支持嵌套滚动视图。例如,滚动不适用于垂直方向的 ViewPager2 对象内的垂直滚动视图。

假设您的 RecyclerView 没有使用与viewPager 相同的方向,您可以自行运行您的片段并调试以确定onLoadMore 是否在不在viewPager 上下文中时实际被触发/容器。

作为旁注,请抽出时间阅读Paging3 及以后的内容。

【讨论】:

RecyclerView 实际上和 ViewPager 使用相同的方向,都是垂直的。【参考方案2】:

我最终通过使用不同的无限滚动 RecyclerView 类解决了这个问题:

https://***.com/a/26561717/14968122

【讨论】:

以上是关于RecyclerView无限滚动在ViewPager2中不起作用的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 StaggeredGridLayoutManager 在 recyclerview 中实现无限滚动(分页)

如何使Horizo​​ntal Recyclerview无限滚动而不滚动回第一项

AdapterView 和 RecyclerView 的连续滚动

使用 staggeredGridLayoutManager 和 recyclerView 进行分页

Recyclerview DiffUtil 项目更新

EndlessRecyclerOnScrollListener 与 Asynctask 的 Endless RecyclerView