Android ViewPager 中的 setCurrentItem 不会立即滚动到正确的位置
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12008716/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
setCurrentItem in ViewPager not scroll immediately in the correct position
提问by MARM
I use a PagerAdapter
. I have a lot of elements so I don't load all elements in the same time. I reload the adapter, I change the old elements by the new elements. For example I have 4 elements, when I arrive at the last element, I reload the elements and I call setCurentItem(1)
to be able to show the viewpager in position one. I have done a lot of tests. I put:
我使用一个PagerAdapter
. 我有很多元素,所以我不会同时加载所有元素。我重新加载适配器,通过新元素更改旧元素。例如,我有 4 个元素,当我到达最后一个元素时,我重新加载元素并调用setCurentItem(1)
以便能够在第一个位置显示 viewpager。我做了很多测试。我放:
viewPager.setCurrentItem(1,false); //But not scroll, put drastically the new page.
viewPager.setCurrentItem(1);
I have tried to modify onPageScrollStateChanged(int arg0)
, I only have 3 views and always ubicate in the middle.
我试图修改onPageScrollStateChanged(int arg0)
,我只有 3 个视图并且总是在中间 ubicate。
if (arg0 == ViewPager.SCROLL_STATE_DRAGGING) {
if(focusedPage==2) {
//Modify adapter
viewPager.setCurrentItem(1,false);
}else if(focusedPage==0){
//Modify adapter
viewPager.setCurrentItem(1,false);
}
And I have tryed to modify onPageSelected(int arg0)
我已经尝试修改 onPageSelected(int arg0)
focusedPage=arg0;
Using this last example I have scroll the views immediately but always it located on the last page. Anybody know how I can slide.
使用最后一个示例,我立即滚动视图,但它始终位于最后一页。有谁知道我是怎么滑的。
Thank you
谢谢
回答by Jorge Aguilar
Can I know more about the background of what you are trying to accomplish?
我可以更多地了解您想要完成的工作的背景吗?
Anyway, from what I can understand you are trying to make an "infinite" ViewPager
going from the last one to the first and vice versa (please correct me if I am wrong). And you want your ViewPager
to go to the first page but scrolling - not just appearing from nowhere.
无论如何,据我所知,您正在尝试ViewPager
从最后一个到第一个“无限” ,反之亦然(如果我错了,请纠正我)。并且您希望您ViewPager
转到第一页但滚动 - 而不仅仅是从任何地方出现。
Well, if you disable the smooth scroll (the second parameter), then it will go directly to the page you want with no scroll motion (and will not "change" to the other pages on the way), and if you enable the smooth scroll then it will go through all the views, so you will see how it was not the next one but the first one.
好吧,如果您禁用平滑滚动(第二个参数),那么它将直接转到您想要的页面而没有滚动运动(并且不会在途中“更改”到其他页面),并且如果您启用平滑滚动然后它将浏览所有视图,因此您将看到它不是下一个而是第一个。
/*No swipe animation, and no onPageChanged for the page in the middle*/
mPager.setCurrentItem(1, false);
/*The same as if you do not add the second parameter*/
mPager.setCurrentItem(1, true);
/*Your ViewPager scrolls through all the needed views until it arrives at that view.*/
mPager.setCurrentItem(1);
What I can recommend to you with this in mind is that you can try to add "dummy" view at positions 0 and "last" and the view in position 0 would be the same as position "last - 1" and the "last" view would be the same as position "1". So you will do everything normal, EXCEPT that on the OnPageChangeListener you will check if the current page is the position "0" or "last" and if it is, you will call setCurrentItem("1", false) or setCurrentItem("last - 1", false) depending on which position you are at now. In this way you will keep the "page change" effect while accomplishing what you want.
考虑到这一点,我可以向您推荐的是,您可以尝试在位置 0 和“last”添加“虚拟”视图,位置 0 中的视图将与位置“last - 1”和“last”相同视图将与位置“1”相同。所以你会做一切正常的事情,除了在 OnPageChangeListener 上你会检查当前页面是位置“0”还是“last”,如果是,你将调用 setCurrentItem("1", false) 或 setCurrentItem("last - 1", false) 取决于您现在所处的位置。通过这种方式,您将在完成您想要的操作的同时保持“页面更改”效果。
I hope this can help you with your problem.
我希望这可以帮助你解决你的问题。
NOTE:It may have a laggy change after you arrive at the new position, because it will have to load the view for the current, next and last views (or if you are on 4.0+ then it will load only the actual position).
注意:到达新位置后,它可能会有滞后的变化,因为它必须加载当前、下一个和最后一个视图的视图(或者如果您使用的是 4.0+,则它只会加载实际位置)。
UPDATE:
更新:
If you change the content of the List/Array that determines the content of the ViewPager
, you need to call:
如果更改确定 内容的 List/Array 的内容,则ViewPager
需要调用:
ViewPager mPager = new ViewPager();
mPager.getAdapter().notifyDataSetChanged(); //This notify that you need to recreate the views
/*This is if you want to change the data and then go to a specific position
If you do not do this you will have a very Buggy Behavior*/
new Handler().post(new Runnable() {
@Override
public void run() {
mPager.setCurrentItem(2); //Where "2" is the position you want to go
}
});
UPDATE 2:
更新 2:
Why do you not add all your elements to the ViewPager
? the ViewPager
already has optimization for handling those cases, in my case I have a lot of elements in it and it is working like a charm.
为什么不将所有元素添加到ViewPager
? 在ViewPager
已经拥有优化处理的情况下,在我的情况我有很多它的元素,它是工作就像一个魅力。
Another thing, in your code I see you change to the middle page each time a page is "settling". But then you really never show the right and left view, so why do you have them?
另一件事,在您的代码中,我看到每次页面“稳定”时您都会更改到中间页面。但是你真的从不显示左右视图,那你为什么要显示它们?
Last thing, when you change your dataset you need to call the "notifyDataSetChanged" method that I mentioned above, and then you call the "setCurrentItem" method inside a handler. If you don't, your app will not work as expected.
最后一件事,当您更改数据集时,您需要调用我上面提到的“notifyDataSetChanged”方法,然后在处理程序中调用“setCurrentItem”方法。如果不这样做,您的应用程序将无法按预期工作。
UPDATE 3:
更新 3:
Well, the only thing I can recommend is having a List where you keep adding the new objects that you bring from the database, and then as long as you keep inserting objects to the end of the List there is no problem. If you want to add objects in the middle or at the beginning then you need to call the notifyDataSetChanged but that is going to be kind of slow because it will generate the views again. We do it this way and it works perfectly and we even download the info from a server, the data is not local (And actually we add info to the end and beginning of the List).
好吧,我唯一可以推荐的是有一个列表,您可以在其中不断添加从数据库中带来的新对象,然后只要您不断将对象插入到列表的末尾,就没有问题。如果要在中间或开头添加对象,则需要调用 notifyDataSetChanged ,但这会有点慢,因为它会再次生成视图。我们这样做,它完美地工作,我们甚至从服务器下载信息,数据不是本地的(实际上我们将信息添加到列表的末尾和开头)。
If you have any other questions about how to achieve this do not hesitate to ask.
如果您对如何实现这一目标有任何其他问题,请随时提出。
UPDATE 4:
更新 4:
Just in case anyone is actually looking for a circular ViewPager
, I added a proof of concept codethat you can re-use. It works without problem and I have used it with complex views and there is still no lag whatsoever.
以防万一有人真的在寻找一个循环ViewPager
,我添加了一个可以重复使用的概念验证代码。它可以毫无问题地工作,我已经将它用于复杂的视图,并且仍然没有任何滞后。
回答by David Figueroa
It doesn't work without a postDelayed, try with this code:
如果没有 postDelayed,它就无法工作,请尝试使用以下代码:
viewPager.postDelayed(new Runnable()
{
@Override
public void run()
{
viewPager.setCurrentItem(num, true);
}
}, 100);