How to make a ViewPager loop?

后端 未结 5 372
独厮守ぢ
独厮守ぢ 2020-12-02 19:34

I have a ViewPager with some views. I\'d like to go to the first one after right swiping on the last one.

I tried

@Override
public Fragment getItem(i         


        
相关标签:
5条回答
  • 2020-12-02 20:00

    this should do the job without dummy pages:

    private boolean isFirstOrLastPage;
    private int currentPageIndex = 0;
    
    
    @Override
    public void onPageScrolled(int arg0, float arg1, int arg2) {
        if(currentPageIndex!=arg0){
            isFirstOrLastPage = false;
            return;
        }
        if((arg0==0 || arg0==PAGES.size()-1) && arg1 == 0 && arg2 == 0){
            if(isFirstOrLastPage){
                     //DO SOMETHING
            }else{
                isFirstOrLastPage = true;
            }
        }
    }
    
    @Override
    public void onPageSelected(int arg0) {
        currentPageIndex = arg0;
    }
    
    0 讨论(0)
  • 2020-12-02 20:04

    One possibility is setting up the screens like this:

    C' A B C A'

    C' looks just like C, but when you scroll to there, it switches you to the real C. A' looks just like A, but when you scroll to there, it switches you to the real A.

    I would do this by implementing onPageScrollStateChanged like so:

    @Override
    public void onPageScrollStateChanged (int state) {
        if (state == ViewPager.SCROLL_STATE_IDLE) {
            int curr = viewPager.getCurrentItem();
            int lastReal = viewPager.getAdapter().getCount() - 2;
            if (curr == 0) {
                viewPager.setCurrentItem(lastReal, false);
            } else if (curr > lastReal) {
                viewPager.setCurrentItem(1, false);
            }
        }
    }
    

    Note that this calls the alternate form of setCurrentItem and passes false to cause the jump to happen instantly rather than as a smooth scroll.

    There are two main drawbacks I see to this. Firstly, upon reaching either end the user has to let the scrolling settle before they can go further. Secondly, it means having a second copy of all of the views in your first and last page. Depending on how resource-heavy your screens are, that may rule out this technique as a possible solution.

    Note also that since the view pager doesn't let clicks go through to underlying controls until after the scrolling has settled, it's probably fine to not set up clicklisteners and the like for the A' and C' fragments.

    Edit: Having now implemented this myself, there's another pretty major drawback. When it switches from A' to A or C' to C, the screen flickers for a moment, at least on my current test device.

    0 讨论(0)
  • 2020-12-02 20:07

    this works, the accepted answer no good because there is a lag when the loop happens:

     @Override
    public int getCount() {
        return Integer.MAX_VALUE;
    }
    
    @Override
    public CharSequence getPageTitle(int position) {
        String title = mTitleList.get(position % mActualTitleListSize);
        return title;
    }
    
    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        int virtualPosition = position % mActualTitleListSize;
        return super.instantiateItem(container, virtualPosition);
    }
    
    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        int virtualPosition = position % mActualTitleListSize;
        super.destroyItem(container, virtualPosition, object);
    }
    

    answer taken from here : ViewPager as a circular queue / wrapping

    0 讨论(0)
  • 2020-12-02 20:19

    I would create a dummy page at the end of the ViewPager. Then I use this code to go to the first page when the user scroll to the dummy page. I know it's far from perfect :D

    @Override
    public void onPageScrolled(int position, float arg1, int arg2) {
        if (position >= NUM_PAGE-1) {
            mViewPager.setCurrentItem(0, true);
        }
    }
    
    0 讨论(0)
  • 2020-12-02 20:23

    My solution is based on benkc, but first and last page scroll animation are disabled, and when pages "scrolled" to real page, scroll animation is enable again, this scheme can solve the first drawback.

    but my ViewPager.setCurrentItem(position, false) result is still have scroll animation, so i implements animation which is too fast to seen.

    the fast scrolling animation like this, don't mind the comment, just my code didn't use these method:

    public class FixedSpeedScroller extends Scroller {
        private int mDuration = 0;
    
        public FixedSpeedScroller(Context context) {
            super(context);
        }
    
        @Override
        public void startScroll(int startX, int startY, int dx, int dy, int duration) {
            super.startScroll(startX, startY, dx, dy, mDuration);
        }
    
        @Override
        public void startScroll(int startX, int startY, int dx, int dy) {
            super.startScroll(startX, startY, dx, dy, mDuration);
        }
    }
    

    and use this method to viewpager's activity

    private Scroller scroller;
    private void setViewPagerScroll(boolean instant) {
        try {
            Field mScroller = null;
            mScroller = ViewPager.class.getDeclaredField("mScroller");
            mScroller.setAccessible(true);
            if (scroller == null) {
                scroller = (Scroller) mScroller.get(mViewPager);
            }
            FixedSpeedScroller fss = new FixedSpeedScroller(mViewPager.getContext());
            mScroller.set(mViewPager, instant ? fss : scroller);
    
        } catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }
    

    and modify onPageScrollStateChanged like this, only first page or last page (i have 5 pages) would change animation to fast scrolling, otherwise has normal scrolling:

    public void onPageScrollStateChanged(int state) {
        if (state == ViewPager.SCROLL_STATE_IDLE) {
            if (position == 0) {
                setViewPagerScroll(true);
                mViewPager.setCurrentItem(3);
    
            } else if (position == 4) {
                setViewPagerScroll(true);
                mViewPager.setCurrentItem(1);
    
            } else {
                setViewPagerScroll(false);
            }
        }
    }
    

    FixedSpeedScroller references is here: http://blog.csdn.net/ekeuy/article/details/12841409

    0 讨论(0)
提交回复
热议问题