Android: 实现双向无限滚动的Viewpager

9

我想要的:

我一直在尝试在Android中实现双向无限循环的viewpager,包括从左到右从右到左

我做的:

我已经实现了无限循环的viewpager适配器,对于从右到左的方向它很正常工作。我通过 viewPager.setCurrentItem(Integer.MAX_VALUE/2); 设置了当前项目位置。

参考资料:

enter image description here

感激不尽。


尝试使用这个库 https://github.com/daimajia/AndroidImageSlider - rusted brain
4个回答

10

尝试查看下面的FragmentPagerAdapter以获取无限的viewpager适配器:

public static class MyAdapter extends FragmentPagerAdapter {
public MyAdapter(FragmentManager fm) {
    super(fm);
}

@Override
public int getCount() {
    return Integer.MAX_VALUE;
}

@Override
public Fragment getItem(int position) {
    return getFragmentBasedOnPosition(position);
}

private Fragment getFragmentBasedOnPosition(int position) {
    int fragmentPos = position % 3; // Assuming you have 3 fragments
    switch(fragmentPos) {
        case 0:
        return Fragment1.newInstance();
        case 1:
        return Fragment2.newInstance();
        case 2:
        return Fragment3.newInstance();
    }
 }
}

我在这里找到了解决方案。

希望它能对你有所帮助。


2
感谢您的支持,但正如我所说,我想要一个双向适配器,这意味着如果我在第0个位置并向左滑动,则应将其移动到viewpager的最后一项。我已经通过https://dev59.com/uWsz5IYBdhLWcg3wn5Xa实现了我的目标,并将我的当前位置设置为Integer.MAX_VALUE / 2,但仍然希望像playstore应用程序一样。 - Hiren Patel
2
@HirenPatel 这个应该是可以工作的,但他忘了说viewPager应该从中间开始,这样就不会让你轻易地到达最右边的边缘。 - android developer
如果我不知道在ViewPager上添加的片段数量怎么办? - Shashwat Gupta

3
我已经制作了自己的解决方案。我创建了一个支持无限循环效果、智能自动滚动、与任何指示器兼容且易于使用的ViewPager。特别是将其用作应用程序的横幅,只需简单的项目页面即可。
我的自定义ViewPager可以:
- 插拔式,易于使用 - 无限循环项目 - 自动滚动项目,允许配置,在活动/片段恢复/暂停时自动恢复/暂停 - 如果只有1个项目,则不会滚动或循环 - 兼容许多指示器
Github链接:https://github.com/kenilt/LoopingViewPager

enter image description here

希望对您有所帮助!

2
实现 ViewPager2 的这个简单方法有三个基本思路:
  1. 将数据模型集合的第一个和最后一个项目添加到同一集合的末尾和开头。例如,listOf(1, 2, 3, 4, 5) 应变为 listOf(5, 1, 2, 3, 4, 5, 1)
  2. 设置 pager 以从索引 1 开始。
  3. 当用户滚动到索引 0 时,使 pager 立即滚动到倒数第二个索引。当用户滚动到最后一个索引时,使 pager 立即滚动到索引 1。
以下是一些示例代码:

1.

private fun <T> List<T>.prepareForTwoWayPaging(): List<T> {
    val first = first()
    val last = last()
    return toMutableList().apply {
        add(0, last)
        add(first)
    }
}
pager.setCurrentItem(1, false)
pager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
    override fun onPageScrolled(
        position: Int,
        positionOffset: Float,
        positionOffsetPixels: Int
    ) {
        // We're only interested when the pager offset is exactly centered. This
        // will help create a convincing illusion of two-way paging.
        if (positionOffsetPixels != 0) {
            return
        }
        when (position) {
            0 -> pager.setCurrentItem(adapter.itemCount - 2, false)
            adapter.itemCount - 1 -> pager.setCurrentItem(1, false)
        }
    }
})

注意: 此代码不会调解任何TabLayout或空数据模型集合。


1
提出的解决方案是正确的,但为了达到结果,您需要将您的viewpager的初始值设置为Integer.MAX_VALUE / 2。
无论如何,我不太喜欢这个解决方案,将getCount设置为返回Integer.MAX_VALUE可能会对应用程序性能产生巨大影响。
我想出了一个解决方案,以避免使用: onPageScrollStateChanged监听器
我只需重新排序片段列表,更新viewPager并移动到新页面而不使用动画,结果是在两个方向上的无限循环。
mainViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener()
{
  Boolean first = false;
  Boolean last = false;

  @Override
  public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
  {}

  @Override
  public void onPageSelected(int position)
  {
    if (position == 0)
    {
      first = true;
      last = false;
    }
    else if (position == mainFragmentList.size() -1)
    {
      first = false;
      last = true;
    }
    else
    {
      first = false;
      last = false;
    }
  }

  @Override
  public void onPageScrollStateChanged(int state)
  {
    if (first && state == ViewPager.SCROLL_STATE_IDLE)
    {
      // Jump without animation
      Fragment fragment = mainFragmentList.get(mainFragmentList.size() -1);
      mainFragmentList.remove(mainFragmentList.size() -1 );
      mainFragmentList.add(0,fragment);
      mainPagerAdapter.setData(mainFragmentList);
      mainPagerAdapter.notifyDataSetChanged();
      Log.e(TAG,mainFragmentList.toString());
      mainViewPager.setCurrentItem(1,false);
    }
    if(last && state == ViewPager.SCROLL_STATE_IDLE)
    {
      // Jump without animation
      Fragment fragment = mainFragmentList.get(0);
      mainFragmentList.remove(0);
      mainFragmentList.add(fragment);
      mainPagerAdapter.setData(mainFragmentList);
      mainPagerAdapter.notifyDataSetChanged();
      Log.e(TAG,mainFragmentList.toString());
      mainViewPager.setCurrentItem(mainFragmentList.size()-2,false);
    }
  }
});

这里发生了什么: 在这个例子中,我们有4个片段A-B-C-D 如果用户在第一个片段A上,新的列表将变为:D-A-B-C [删除最后一个并作为第一个推送] 我更新ViewPager并再次移动(无动画)到片段A,所以索引为1。 现在用户可以继续向左滚动,会找到片段D。
最后一个片段也是同样的情况: 重新从A-B-C-D开始 如果用户在最后一个片段D上,新的列表将变为:B-C-D-A [删除第一个并作为最后一个推送] 我更新ViewPager并再次移动(无动画)到片段D,所以索引为mainFragmentList.size()-2。 现在用户可以继续向右滚动,会找到片段A。
记得实现FragmentStatePagerAdapter而不是FragmentPagerAdapter。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接