在无限的 ViewPager 中从最右边开始

Start at ultimate right in an infinite ViewPager

我有一个ViewPager,我想提供理论上无限数量的页面。每个页面都包含一个链接到日期的文本,并且滑动用户应该能够看到以前日期的文本。他看不到未来日期的短信。

为此,我将 ViewPager 作为计数 Integer.MAX_VALUE。但是,我希望默认页面是最终的右侧页面,以便向左滑动可以显示以前日期的文本。默认情况下,第一个位置是最终离开的。

这是我的代码:

private class PagerAdapter extends FragmentStatePagerAdapter {
    public PagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int i) {
        return new DailyTextFragment();
    }

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

    @Override
    public CharSequence getPageTitle(int position) {
        return "OBJECT " + (position + 1);
    }
}

我试过 setCurrentPosition(Integer.MAX_VALUE),但随后 Android 尝试计算所有页面 最后一个页面之前 ,我得到了一个java.lang.OutOfMemoryError

我考虑过让 ViewPager 认为触摸事件的 x 坐标是镜像的,但不确切地知道该怎么做如果这是最好的解决方案。设置这种界面的最佳方式是什么?

经过更多的调试,我发现了以下内容:

  • 当您尝试设置 setCurrentPosition(Integer.MAX_VALUE) 时,FragmentStatePageAdapter 将尝试创建一个包含 2147483647 个 NULL 对象的 ArrayList。因此,您 运行 内存不足。
  • 实际上,只有前两个片段(0 和 1)被实例化:其余 ArrayList 是 NULL 值。

这在instantiateItem()中实现如下:

while (mFragments.size() <= position) {
    mFragments.add(null);
}

现在,我们可以做的是通过如下重写此方法来欺骗 FragmentStatePageAdapter

@Override
public Object instantiateItem(ViewGroup container, int position) {
    if (position < 2) {
        return super.instantiateItem(container, position);
    } else {
        return super.instantiateItem(container, Integer.MAX_VALUE - position - 1);
    }
}

因此,对于前两个对象,我们为 super 方法提供实数 - 对于其他对象,我们为其提供 Integer.MAX_VALUE - position。现在,您可以在 activity 的 onCreate 方法中安全地执行此操作,例如:

pager.setCurrentItem(Integer.MAX_VALUE, false);

像这样,ViewPager 将从最右边开始,使用对象 0。因此,您的对象是相反的:对象 0 是最后一个,在最右边,再往左是您的对象片段的索引增加。

您还需要覆盖 destroyItem(),因为它有相同的循环来添加 NULL 值。像这样:

@Override
public void destroyItem(ViewGroup container, int position, Object object) {
    if (position < 2) {
        super.destroyItem(container, position, object);
    } else {
        super.destroyItem(container, Integer.MAX_VALUE - position - 1, object);
    }
}

这可能不是执行此操作的首选方法,但它对我有用。