在无限的 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);
}
}
这可能不是执行此操作的首选方法,但它对我有用。
我有一个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);
}
}
这可能不是执行此操作的首选方法,但它对我有用。