ViewPager 作为循环队列/包装
我使用 ViewPager
和 FragmentStatePagerAdapter
来允许在某些片段之间导航。
假设我有三个片段:A
、B
和 C
。 ViewPager 最初显示片段 A,并允许您通过从右向左滑动来导航到片段 B,然后通过再次滑动来导航到片段 C。这允许以下导航路径:A <--> B<--> C。
我想要的是能够在片段 A 上从左向右滑动并让 ViewPager 显示片段 C,即让它表现为循环队列并允许 ... --> C<--> A<--> B<--> C<--> A <-- ...
我不希望片段在其他位置重复(即最终出现超过三个实例)。
ViewPager 可以实现这种包装功能吗?
I am using a ViewPager
with the FragmentStatePagerAdapter
to allow navigation between some fragments.
Let's say I have three fragments: A
, B
and C
. The ViewPager shows Fragment A initially, and allows you to navigate to Fragment B by swiping from right-to-left, and then to Fragment C by swiping again. This allows the following navigation paths: A <--> B <--> C
.
What I would like is to be able to swipe from left-to-right on Fragment A and have the ViewPager show Fragment C, i.e. for it to behave as a circular queue and allow ... --> C <--> A <--> B <--> C <--> A <-- ...
I do not want the Fragments duplicated in other positions (i.e. ending up with more than three instances).
Is this wrapping functionality possible with a ViewPager?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(14)
我已经实现了一个 ViewPager/PagerAdapter ,它可以允许伪无限分页行为。它的工作原理是指定一个非常大的数字作为实际计数,但将它们映射到数据集/页面集的实际范围。它还将开头偏移了很大的数字,以便您可以立即从“第一”页滚动到左侧。
一旦你到达第 1,000,000 页,它就不再那么有效了(滚动时你会看到图形故障),但这通常不是现实世界的用例。我可以通过偶尔将计数重置为较低的数字来解决此问题,但我暂时保留它的原样。
InfinitePagerAdapter 包装了现有的 ViewPager,因此使用非常透明。
InfiniteViewPager
确实做了一些工作来确保您可以向左和向右滚动多次。https://github.com/antonyt/InfiniteViewPager
I've implemented a ViewPager/PagerAdapter that can allow for pseudo-infinite paging behaviour. It works by specifying a very large number as the actual count, but maps them to the actual range of the dataset/pageset. It offsets the beginning by a large number also so that you can immediately scroll to the left from the 'first' page.
It doesn't work so well once you get to 1,000,000th page (you will see graphical glitches when scrolling), but this is typically not a real-world use-case. I could fix this by resetting the count to a lower number once in a while, but I will leave it how it is for now.
The
InfinitePagerAdapter
wraps an existing ViewPager, and so the usage is quite transparent. TheInfiniteViewPager
does does a bit of work to make sure you can potentially scroll to the left and right many times.https://github.com/antonyt/InfiniteViewPager
这是一个没有假页面的解决方案,并且工作起来就像一个魅力:
您只需将其设置为 ViewPager 作为 onPageChangeListener 即可:( ** 现在已弃用 ** 检查编辑注释)
以避免在 ViewPager 的“末尾”出现蓝色光芒,您应该将此行应用到放置 ViewPager 的 xml 中:
我们改进了上面的解决方案,并在 github。请随意检查一下:)
编辑::根据@Bhavana评论,只需使用addOnPageChangeListener而不是setOnPageChangeListener,因为稍后已弃用。
This is a solution without fake pages and works like a charm:
You just have to set it to your ViewPager as onPageChangeListener and that's it: ( ** deprecated now ** check the edit notes)
To avoid having this blue shine at the "end" of your ViewPager you should apply this line to your xml where the ViewPager is placed:
We have improved the solution above and created a little library on github. Feel free to check it out :)
Edit:: As per the @Bhavana comment , Just use addOnPageChangeListener instead of setOnPageChangeListener as later is deprecated.
另一种方法是将视图分页器中第一个元素的假副本添加到适配器的末尾,并将最后一个元素的假副本添加到开头。然后,当您查看视图寻呼机中的第一个/最后一个元素时,无需动画即可更改页面。
所以基本上,视图寻呼机中的第一个/最后一个元素是假的,只是为了生成正确的动画,然后切换到结束/开始。
例子:
Another way to do this is to add a fake copy of the first element in the view pager to the end of your adapter, and a fake copy of the last element to the beginning. Then when you are viewing the first/last element in the view pager, change pages without animating.
So basically, the first/last elements in your view pager are fakes, just there to produce the correct animation, and then switch over to the end/beginning.
Example:
我一直在尝试所有的建议、解决方案、库等,但它们不是纯粹的循环,而且大多数时候不支持仅 3 页。
因此,我使用新的
ViewPager2
实现了一个循环ViewPager
示例,新的ViewPager
使用RecyclerView
和ViewHolder 来处理视图回收并按预期工作!
TLDR: GITHUB
在此示例中,将使用 < code>ViewPager2 和一个
FragmentPagerAdapter
支持 3 个或更多页面之间的循环导航。我正在使用库
androidx.viewpager2:viewpager2
的 alpha 版本,但版本1.0.0-alpha06
是 Google 冻结 API 并移动之前计划的最后一个版本到测试版。1。将
ViewPager2
库添加到 build.gradle 中的依赖项2.将
ViewPager2
视图添加到您的项目中:3.创建
FragmentStateAdapter
适配器:getItemCount()
需要返回一个巨大的数字。 (2147483647)getCenterPage()
根据 huuuuge 编号返回中心页面。该方法用于获取在
ViewPager2
中设置的初始页面的位置,在这种情况下用户需要滑动〜1073741823次才能到达ViewPager2
的末尾。HomeScreens 是一个包含页面信息的 ENUM。
4.将适配器设置为ViewPager
I've been trying all the suggestions, solutions, libraries, etc but they're not pure circular and most of the time don't have support for only 3 pages.
So I implemented a circular
ViewPager
example using the newViewPager2
, the newViewPager
uses aRecyclerView
andViewHolder
s to handle the views recycling and works as expected!TLDR: GITHUB
In this example, will be building a single activity app with
ViewPager2
and aFragmentPagerAdapter
supporting circular navigation between 3 pages or more.I'm using an alpha version of the library
androidx.viewpager2:viewpager2
, but the version1.0.0-alpha06
is the last one planned before google freezing the API and moving to beta.1. Add the
ViewPager2
library to the dependencies in your build.gradle2. Add the
ViewPager2
view to your project:3. Create the
FragmentStateAdapter
adapter:getItemCount()
needs to returns a huuuuge number. (2147483647)getCenterPage()
returns the central page based on the huuuuge number.This method is used to get the position of the initial page to set in the
ViewPager2
, in this case the user needs to swipe ˜1073741823 time to reach the end of theViewPager2
.HomeScreens is a ENUM with the page info.
4. Set the adapter to the ViewPager
刚刚看到这个问题,找到了解决办法。 解决方案链接
对 onPageScrollStateChanged 函数进行以下更改。假设您有 4 个选项卡。
如果 state 变量位于现有选项卡中,则其值为 1。
一旦您尝试在第一个选项卡之前或之后导航,该变量就会变为 0你的最后一个标签。因此,比较之前和当前的状态,如代码所示,就完成了。
请参阅 onPageScrollStateChanged 函数此处。
希望有帮助。
Just now saw this question and found a solution. Solution Link
Make the following changes to your onPageScrollStateChanged function. Consider you have 4 tabs.
If the state variable is in the existing tabs, its value is 1.
It becomes 0 once you try to navigate before your first tab or after your last tab. So, compare the previous and current states, as shown in the code and you are done.
See onPageScrollStateChanged function here.
Hope it helps.
这几乎完成了antonyt想要的,它不会让你从A->;尽管是C。 (未经严格测试,但似乎工作得足够好)
This almost accomplishes what antonyt wants, it wont let you go from A -> C though. (Not tested vigorously, but seems to work well enough)
如何实现这一点的简单想法。当您的数组包含页面时,只需将此数组添加到正好位于中间的另一个数组中即可。
例如,您有一个包含 15 个元素的数组。因此,将其放入中间的 400 个元素数组中(200 个位置),
然后只需向左和向右填充数组,以便可以四处移动。
示例图片:
它看起来怎么样?
https://youtu.be/7up36ylTzXk
让代码说话:)
https://gist.github.com/gelldur/051394d10f6f98e2c13d
Simple idea how to achieve this. When you have your Array with pages simply add this array to another array exactly in the middle.
For example you have array with 15 elements. So place it into 400 element array in the middle (200 position)
Next simply fill array to the left and right so you can move around.
Sample image:
How it looks?
https://youtu.be/7up36ylTzXk
Let the code talk :)
https://gist.github.com/gelldur/051394d10f6f98e2c13d
我有一个我相信会起作用的解决方案。它没有经过测试,但它是:
FragmentPagerAdapter 的包装器作为超类:
然后标准 FragmentPagerAdapter 实现子类化了这个新的抽象类:
以及 Cyclic Pager Adapter 实现。
ViewPager初始化
最后是回调实现:
I have a solution I believe will work. It isn't tested, but here it is:
A wrapper around FragmentPagerAdapter as the super class:
Then the standard FragmentPagerAdapter implementation subclass this new abstract class:
And the Cyclic Pager Adapter implementation.
ViewPager initialization
And finally, the callback implementation:
在 onCreate(Bundle savingInstanceState) 上设置页面 500000/2 的当前项目
On onCreate(Bundle savedInstanceState) set current item for page 500000/2
在初始化代码中的某处选择真正的第一个元素:
修改 setOnPageChangeListener:
<预><代码> @Override
公共无效onPageSelected(int状态){
如果(状态==ITEMS_NUMBER + 1){
mViewPager.setCurrentItem(1, false);
} 否则如果(状态== 0){
mViewPager.setCurrentItem(ITEMS_NUMBER, false);
}
}
select real First Element somewhere in init code:
modify setOnPageChangeListener:
基于这种方法
真正的循环,寻呼机标题栏,真正的无刷新滚动
视图页面适配器:
使用:
based on this approach
true loop, pager title strip, true no refresh scrolling
view page adapter:
using:
您可以使用 https://github.com/pozitiffcat/circularview
中的简单视图
其特点之一是:
示例:
You may use simple view from https://github.com/pozitiffcat/cyclicview
One of features is:
Example:
我的答案可能与其他人的答案类似。但是我无法在 ViewPager2 中使用 FragmentStateAdapter 找到解决方案。
其中 Fragment1 是第一个显示的。
在您的 MainActivity (或任何具有 ViewPager 的活动)中:
您显然必须根据您拥有的 Fragment 数量更改位置。
My answer is probably similar to others out there. However I couldn't find a solution in ViewPager2 with FragmentStateAdapter.
Where Fragment1 is the first to be displayed.
The in your MainActivity (or whichever activity has the ViewPager):
You'll obviously have to change the positions depending on the number of Fragments you have.
抱歉耽搁了,但我已经看到了答案,但我无法坚持,也必须回答:)。
在您的适配器上,在方法 get count 上,按以下步骤操作:
这会起作用!
Sorry for the delay, but I've seen the answers and I I was unable to hold, got to answer it too :).
On your adapter, on the method get count, proceed as follows:
That will work!