我有一个带有ViewPager的Activity,它显示了一堆图片。启动时,ViewPager的位置根据用户在上一个Activity中选择的内容进行设置。与画廊类似。
我希望每次选择新页面时都会调用onPageSelected,即首次打开“活动”或用户滑动到新页面时。
我设置起点如下:
mPager.setCurrentItem(index);
一切正常,除非在将index设置为0的情况下调用setCurrentItem,因为这不会触发onPageSelected。
mPager.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageSelected(int index) {
Log.d(TAG, "onPageSelected " + index);
}
...
}
所以我的问题是;这是一个错误,如果是这样我该怎么办呢?
答案 0 :(得分:78)
到目前为止我发现的最干净的解决方案是引用你在ViewPager上设置的onPageChangeListener(因为我认为没有ViewPager.getOnPageChangeListener()方法),然后你设置了ViewPager的适配器,调用:
onPageChangeListener.onPageSelected(viewPager.getCurrentItem());
但是,当前索引处的页面片段尚未实例化(至少如果您使用的是FragmentStatePagerAdapter),因此您可能需要将其包装在runnable中,ala:
viewPager.post(new Runnable(){
@Override
public void run() {
onPageChangeListener.onPageSelected(viewPager.getCurrentItem());
}
});
此外,如果在onPageSelected处理程序中需要对片段的引用,则必须自己执行此操作。我为FragmentStatePagerAdapter使用了一个抽象基类,它覆盖了实例化和销毁方法,并添加/删除了SparseArray中的片段。
答案 1 :(得分:33)
好的,所以我无法弄清楚这是一个错误(或一个功能)。但我想我会分享一个可能解决问题的方法。
在Activity中的方法中编写您想要执行的功能,然后在onPageSelected方法中调用它。
mPager.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageSelected(int index) {
myOnPageSelectedLogic(index);
}
...
}
然后在致电后立即
setCurrentItem(index);
在Activity中,添加以下if语句
if(index == 0) {
myOnPageSelectedLogic(0);
}
这不是超级漂亮,但我希望它可以帮助某人:)
答案 2 :(得分:23)
其实我认为这是一个BUG。 我查看了ViewPager的源代码,找到了 onPageSelected 的唯一触发器:
if (dispatchSelected && mOnPageChangeListener != null) {
mOnPageChangeListener.onPageSelected(item);
}
以上,变量 dispatchSelected 由代码确定:
final boolean dispatchSelected = mCurItem != item;
//item is what you passed to setCurrentItem(item)
并且,变量 mCurItem 被定义并初始化为:
private int mCurItem; // Index of currently displayed page.
所以 mCurItem 默认为0.调用setCurrentItem(0)时, dispatchSelected 将为false,因此不会调度onPageSelected()。
现在我们应该理解为什么调用setCurrentItem(0)是一个问题而setCurrentItem(1或2,3 ...)不是。
如何解决这个问题:
将ViewPager的代码复制到您自己的项目并修复它:
from
final boolean dispatchSelected = mCurItem != item; //the old line
to
final boolean dispatchSelected = mCurItem != item || mFirstLayout; //the new line
然后使用您自己的ViewPager。
由于您有意识地调用了setCurrentItem(0)并且对OnPageChangedListener有所了解,因此请自行调度onPageSelected()。
听楼下怎么说...
答案 3 :(得分:1)
以下解决方案似乎对我有用。即,当首次加载viewpager时,我在位置0处获得回调,并且从用户滚动或setCurrentItem(x)调用中获得所有后续选择的回调。我没有观察到任何不良行为。
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if (positionOffsetPixels == 0) {
//Do something on selected page at position
}
}
@Override
public void onPageSelected(int position) {}
@Override
public void onPageScrollStateChanged(int state) {}
});
答案 4 :(得分:0)
onPageSelected
。对于这种情况,我手动执行所有需要的操作。另外,我认为对onPageSelected(0)
的调用也应该有效。
答案 5 :(得分:0)
当位置从0更改为0时,您可以扩展ViewPager
并自己调用监听器
public class BetterViewPager extends ViewPager {
public BetterViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
// we some the listner
protected OnPageChangeListener listener;
@Override
public void setOnPageChangeListener(OnPageChangeListener listener) {
super.setOnPageChangeListener(listener);
this.listener = listener;
}
@Override
public void setCurrentItem(int item) {
// when you pass set current item to 0,
// the listener won't be called so we call it on our own
boolean invokeMeLater = false;
if(super.getCurrentItem() == 0 && item == 0)
invokeMeLater = true;
super.setCurrentItem(item);
if(invokeMeLater && listener != null)
listener.onPageSelected(0);
}
}
答案 6 :(得分:0)
public class PageChangeListener implements ViewPager.OnPageChangeListener {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
if (state == ViewPager.SCROLL_STATE_IDLE && getCurrentItem() == 0) {
//this indicate viewpager finish scroll and page at position 0 is selected.
}
答案 7 :(得分:0)
最简单的解决方案是使用功能,例如
viewpager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrollStateChanged(int state) {}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}
@Override
public void onPageSelected(int position) {
onPage(position);
}
});
// call first time
onPage(0);
private void onPage(int position) {
//...
}
答案 8 :(得分:-1)
如果ViewPager在片段中,则在onViewCreated方法中调用mPager.setOnPageChangeListener(this)
答案 9 :(得分:-4)
如果你不关心屏幕动态尝试
pager.setCurrentItem(1);
pager.setCurrentItem(0);