ViewPager.setCurrentItem 仅适用于/ smooth Scroll 设置为 true
ViewPager.setCurrentItem only works w/ smoothScroll set to true
我已经创建了 FragmentPagerAdapter
的无限扩展(在 this site 上有关于如何实现它的示例)。这允许我迭代 50(任意数量)组 52 个片段(每周一个)从而给用户无限的片段感觉。
当通过调用 ViewPager.setCurrentItem
在片段之间 scrolling/jumping 时,我看到两种情况:
- 无论哪种方式都只跳一个片段 - 一切正常。这大概是由于
ViewPager.setCurrentItemInternal
中专门针对此用例的代码(查找以 We are doing a jump by more than one page
开头的注释)
- 跳转多个片段,只有在
smoothScroll
设置为true
时调用setCurrentItem
才能在屏幕上正确显示新片段(即setCurrentItem(i, true)
);否则会出现黑屏
据我所知,这可能是因为 ViewPager.scrollToItem
中包含以下代码:
if (smoothScroll) {
smoothScrollTo(destX, 0, velocity);
if (dispatchSelected) {
dispatchOnPageSelected(item);
}
} else {
if (dispatchSelected) {
dispatchOnPageSelected(item);
}
completeScroll(false);
scrollTo(destX, 0);
pageScrolled(destX);
}
这是我无法理解的地方。为什么这个 if/else
会导致我遇到的现象?
解释很简单 - ViewPager
不会保留所有片段的状态,因为如果保持所有状态都处于活动状态,这将对性能造成灾难。
有一个 setOffscreenPageLimit
方法正好适用于这种情况。它的目的是定义 ViewPager
应该在当前状态的左侧和右侧保留多少个片段状态。更多背景调查官方文档:https://developer.android.com/reference/android/support/v4/view/ViewPager.html#setOffscreenPageLimit(int)
Set the number of pages that should be retained to either side of the current page in the view hierarchy in an idle state. Pages beyond this limit will be recreated from the adapter when needed.
This is offered as an optimization. If you know in advance the number of pages you will need to support or have lazy-loading mechanisms in place on your pages, tweaking this setting can have benefits in perceived smoothness of paging animations and interaction. If you have a small number of pages (3-4) that you can keep active all at once, less time will be spent in layout for newly created view subtrees as the user pages back and forth.
You should keep this limit low, especially if your pages have complex layouts. This setting defaults to 1.
所以我们可以看到 默认限制是 1 - 这就是为什么只跳一个片段可以完美工作的答案。这也是平滑滚动情况的答案 - 当你想设置新的当前项目时平滑滚动意味着你需要一个一个地滚动所有片段 - 这是默认限制 1 工作的情况。
所以在您的情况下,您可以尝试 setOffscreenPageLimit(52)
,然后 setCurrentItem(50)
应该会按预期工作。 不推荐,只做看看效果。如果你在你的片段中有一些困难的工作(比如从网络加载一些数据)那么它会在启动时有很大的延迟,因为所有的片段都会一次加载。
希望对您有所帮助!
我已经创建了 FragmentPagerAdapter
的无限扩展(在 this site 上有关于如何实现它的示例)。这允许我迭代 50(任意数量)组 52 个片段(每周一个)从而给用户无限的片段感觉。
当通过调用 ViewPager.setCurrentItem
在片段之间 scrolling/jumping 时,我看到两种情况:
- 无论哪种方式都只跳一个片段 - 一切正常。这大概是由于
ViewPager.setCurrentItemInternal
中专门针对此用例的代码(查找以We are doing a jump by more than one page
开头的注释) - 跳转多个片段,只有在
smoothScroll
设置为true
时调用setCurrentItem
才能在屏幕上正确显示新片段(即setCurrentItem(i, true)
);否则会出现黑屏
据我所知,这可能是因为 ViewPager.scrollToItem
中包含以下代码:
if (smoothScroll) {
smoothScrollTo(destX, 0, velocity);
if (dispatchSelected) {
dispatchOnPageSelected(item);
}
} else {
if (dispatchSelected) {
dispatchOnPageSelected(item);
}
completeScroll(false);
scrollTo(destX, 0);
pageScrolled(destX);
}
这是我无法理解的地方。为什么这个 if/else
会导致我遇到的现象?
解释很简单 - ViewPager
不会保留所有片段的状态,因为如果保持所有状态都处于活动状态,这将对性能造成灾难。
有一个 setOffscreenPageLimit
方法正好适用于这种情况。它的目的是定义 ViewPager
应该在当前状态的左侧和右侧保留多少个片段状态。更多背景调查官方文档:https://developer.android.com/reference/android/support/v4/view/ViewPager.html#setOffscreenPageLimit(int)
Set the number of pages that should be retained to either side of the current page in the view hierarchy in an idle state. Pages beyond this limit will be recreated from the adapter when needed.
This is offered as an optimization. If you know in advance the number of pages you will need to support or have lazy-loading mechanisms in place on your pages, tweaking this setting can have benefits in perceived smoothness of paging animations and interaction. If you have a small number of pages (3-4) that you can keep active all at once, less time will be spent in layout for newly created view subtrees as the user pages back and forth.
You should keep this limit low, especially if your pages have complex layouts. This setting defaults to 1.
所以我们可以看到 默认限制是 1 - 这就是为什么只跳一个片段可以完美工作的答案。这也是平滑滚动情况的答案 - 当你想设置新的当前项目时平滑滚动意味着你需要一个一个地滚动所有片段 - 这是默认限制 1 工作的情况。
所以在您的情况下,您可以尝试 setOffscreenPageLimit(52)
,然后 setCurrentItem(50)
应该会按预期工作。 不推荐,只做看看效果。如果你在你的片段中有一些困难的工作(比如从网络加载一些数据)那么它会在启动时有很大的延迟,因为所有的片段都会一次加载。
希望对您有所帮助!