onPageSelected isn't triggered when calling setCurrentItem(0)

后端 未结 10 1710
梦如初夏
梦如初夏 2020-12-22 20:13

I have an Activity with a ViewPager which displays a bunch of pictures. When it starts the ViewPager\'s position is set based on what the user selected in a previous Activit

相关标签:
10条回答
  • 2020-12-22 20:31

    Actually I think this is a BUG. I've check the source code of ViewPager and found the only trigger of onPageSelected:

    if (dispatchSelected && mOnPageChangeListener != null) {
                mOnPageChangeListener.onPageSelected(item);
            }
    

    Above, variable dispatchSelected is determined by code:

    final boolean dispatchSelected = mCurItem != item; 
    //item is what you passed to setCurrentItem(item)
    

    And, variable mCurItem is defined and initialized as:

    private int mCurItem; // Index of currently displayed page.
    

    So mCurItem is default to 0. When calling setCurrentItem(0), dispatchSelected will be false thus onPageSelected() will not be dispatched.

    Now we should understand why calling setCurrentItem(0) is a problem while setCurrentItem(1, or 2, 3...) is not.

    How to solve this problem:

    1. Copy the code of ViewPager to your own project and fix it:

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

      then use your own ViewPager.

    2. Since you consciously called setCurrentItem(0) and have a refrence to the OnPageChangedListener, dispatch the onPageSelected() by yourself.

    3. 听楼下怎么说...

    0 讨论(0)
  • 2020-12-22 20:38

    Ok, so I haven't been able to figure out whether this is a bug (or a feature). But I thought I'd share how a possible solution to the problem could look..

    Write the functionality you wish to perform in a method in the Activity and then call this in the onPageSelected method.

    mPager.setOnPageChangeListener(new OnPageChangeListener() {
        @Override
        public void onPageSelected(int index) {
            myOnPageSelectedLogic(index);
        }
        ...
    }
    

    And then right after calling

    setCurrentItem(index);
    

    in the Activity, add the following if statement

    if(index == 0) {
        myOnPageSelectedLogic(0);
    }
    

    It's not super pretty but I hope it helps someone :)

    0 讨论(0)
  • 2020-12-22 20:41

    You can extend the ViewPager and call the Listener by yourself when the position is changed from 0 to 0

    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);
            }
    
    }
    
    0 讨论(0)
  • 2020-12-22 20:44
    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.
            }
    
    0 讨论(0)
提交回复
热议问题