调用setCurrentItem(0)时不会触发onPageSelected

时间:2012-08-03 10:51:30

标签: android android-viewpager

我有一个带有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);
  }
  ...
}

所以我的问题是;这是一个错误,如果是这样我该怎么办呢?

10 个答案:

答案 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 ...)不是。

如何解决这个问题:

  1. 将ViewPager的代码复制到您自己的项目并修复它:

    from 
    final boolean dispatchSelected = mCurItem != item; //the old line
    to
    final boolean dispatchSelected = mCurItem != item || mFirstLayout; //the new line
    

    然后使用您自己的ViewPager。

  2. 由于您有意识地调用了setCurrentItem(0)并且对OnPageChangedListener有所了解,因此请自行调度onPageSelected()。

  3. 听楼下怎么说...

答案 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);
相关问题