Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make a ViewPager loop?

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(int arg0) {
    int i = arg0 % fragmentList.size();
    return fragmentList.get(i);
}

@Override
public int getCount() {
    return fragmentList.size()+1;
}

But I got an error

E/AndroidRuntime(22912): java.lang.IllegalStateException: Fragment already added: RubricFragment{4136cd80 #1 id=0x7f06000c android:switcher:2131099660:0}
like image 648
J3n Avatar asked Apr 17 '12 08:04

J3n


People also ask

How the ViewPager is implemented?

Implement Swipe Views You can create swipe views using AndroidX's ViewPager widget. To use ViewPager and tabs, you need to add a dependency on ViewPager and on Material Components to your project. To insert child views that represent each page, you need to hook this layout to a PagerAdapter .

How do you get ViewPager fragments?

ViewPager save Fragment in FragmentManager with particular tags, So We can get ViewPager's fragment by FragmentManager class by providing tag. And ViewPager provide tag to each fragment by following syntax : Fragment page = getSupportFragmentManager(). findFragmentByTag("android:switcher:" + R.

When should I use ViewPager?

ViewPager in Android is a class that allows the user to flip left and right through pages of data. This class provides the functionality to flip pages in app. It is a widget found in the support library. To use it you'll have to put the element inside your XML layout file that'll contain multiple child views.


2 Answers

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.

like image 125
benkc Avatar answered Oct 19 '22 14:10

benkc


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);
    }
}
like image 28
homi3kh Avatar answered Oct 19 '22 12:10

homi3kh