8

What I want:

I have been trying to implement two directional Endless viewpager in Android, Left to Right & Right to Left

What I did:

I have implemented Endless viewpager adapter, it works fine for right to left direction, I have set current item position by viewPager.setCurrentItem(Integer.MAX_VALUE/2);.

Reference:

enter image description here

Help would be appreciate.

Hiren Patel
  • 48,538
  • 20
  • 161
  • 144

4 Answers4

10

Try to check below FragmentPagerAdapter to get endless viewpager adapter :

public static class MyAdapter extends FragmentPagerAdapter {
public MyAdapter(FragmentManager fm) {
    super(fm);
}

@Override
public int getCount() {
    return Integer.MAX_VALUE;
}

@Override
public Fragment getItem(int position) {
    return getFragmentBasedOnPosition(position);
}

private Fragment getFragmentBasedOnPosition(int position) {
    int fragmentPos = position % 3; // Assuming you have 3 fragments
    switch(fragmentPos) {
        case 0:
        return Fragment1.newInstance();
        case 1:
        return Fragment2.newInstance();
        case 2:
        return Fragment3.newInstance();
    }
 }
}

I found solution here.

I hope its helps you.

android developer
  • 106,412
  • 122
  • 641
  • 1,128
pRaNaY
  • 21,330
  • 22
  • 85
  • 134
  • 2
    Thanks for support but as I said, I want two directional adapter, means if I am on the 0th position and I do swipe Right to Left then it should be move 0 to last item of viewpager, I have achieved my goal by http://stackoverflow.com/questions/7766630/changing-viewpager-to-enable-infinite-page-scrolling and I set my current position Integer.MAX_VALUE/2 but still looking for something like playstore app. – Hiren Patel Apr 04 '16 at 04:32
  • 2
    @HirenPatel This should actually work, but he forgot to say that the viewPager should start from the middle, so that it won't let you go to the most-right-edge so easily. – android developer Oct 31 '17 at 13:39
  • what if i dont know number of fragments added on Viewpager – Shashwat Gupta Nov 15 '17 at 05:49
3

I have made my own solution. I created a ViewPager that supports infinite looping effect, smart auto-scroll, compatible with any indicators and easy to use. It especially uses it as banners of application with a simple item page.

My custom ViewPager can:

  • Plug and play, easy to use
  • Infinite Looping items
  • Auto-scroll items, allow config, auto-resume/pause when activity/fragment resume/pause
  • Won't scroll or loop if it has only 1 item
  • Compatible with many indicators

Github link: https://github.com/kenilt/LoopingViewPager

enter image description here

Hope it helps!

kenilt
  • 56
  • 1
  • 3
2

One simple way to achieve this for ViewPager2 is with 3 basic ideas:

  1. Add the first and last items of your data model collection to the end and start, respectively, of that same collection. E.g. listOf(1, 2, 3, 4, 5) should become listOf(5, 1, 2, 3, 4, 5, 1).
  2. When setting up the pager, set it to start with index 1.
  3. When the user scrolls to index 0, have the pager scroll instantly to the penultimate index. When the user scrolls to the last index, have the pager scroll instantly to index 1.

Some sample code to do this is as follows:

1.

private fun <T> List<T>.prepareForTwoWayPaging(): List<T> {
    val first = first()
    val last = last()
    return toMutableList().apply {
        add(0, last)
        add(first)
    }
}
pager.setCurrentItem(1, false)
pager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
    override fun onPageScrolled(
        position: Int,
        positionOffset: Float,
        positionOffsetPixels: Int
    ) {
        // We're only interested when the pager offset is exactly centered. This
        // will help create a convincing illusion of two-way paging.
        if (positionOffsetPixels != 0) {
            return
        }
        when (position) {
            0 -> pager.setCurrentItem(adapter.itemCount - 2, false)
            adapter.itemCount - 1 -> pager.setCurrentItem(1, false)
        }
    }
})

Caveat: this code does not reconcile any TabLayout or an empty data model collection.

N1hk
  • 571
  • 4
  • 9
1

The proposed solutions are correct but to achieve the result you need to set the initial value of your viewpager to Integer.MAX_VALUE/2.

Anyway, I don't really like this solution, setting getCount to return Integer.MAX_VALUE can have huge impact on application performance.

I figured out a solution in order to avoid this problem using the:

onPageScrollStateChanged Listener

I simply reorder the fragment list, update the viewPager and move to the new page without animation, the result is an endless loop in both directions:

mainViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener()
{
  Boolean first = false;
  Boolean last = false;

  @Override
  public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
  {}

  @Override
  public void onPageSelected(int position)
  {
    if (position == 0)
    {
      first = true;
      last = false;
    }
    else if (position == mainFragmentList.size() -1)
    {
      first = false;
      last = true;
    }
    else
    {
      first = false;
      last = false;
    }
  }

  @Override
  public void onPageScrollStateChanged(int state)
  {
    if (first && state == ViewPager.SCROLL_STATE_IDLE)
    {
      // Jump without animation
      Fragment fragment = mainFragmentList.get(mainFragmentList.size() -1);
      mainFragmentList.remove(mainFragmentList.size() -1 );
      mainFragmentList.add(0,fragment);
      mainPagerAdapter.setData(mainFragmentList);
      mainPagerAdapter.notifyDataSetChanged();
      Log.e(TAG,mainFragmentList.toString());
      mainViewPager.setCurrentItem(1,false);
    }
    if(last && state == ViewPager.SCROLL_STATE_IDLE)
    {
      // Jump without animation
      Fragment fragment = mainFragmentList.get(0);
      mainFragmentList.remove(0);
      mainFragmentList.add(fragment);
      mainPagerAdapter.setData(mainFragmentList);
      mainPagerAdapter.notifyDataSetChanged();
      Log.e(TAG,mainFragmentList.toString());
      mainViewPager.setCurrentItem(mainFragmentList.size()-2,false);
    }
  }
});

This is what happens here: in this example, we have 4 fragments A-B-C-D if the user is on fragment A (first), the new List will become: D-A-B-C [remove the last and push as first] I update the ViewPager and move (without animation) again to fragment A so index 1. Now the user can continue to scroll left and will find fragment D.

Same thing with the last fragment: starting again with A-B-C-D if the user is on fragment D (last), the new List will become: B-C-D-A [remove the first and push as last] I update the ViewPager and move (without animation) again to fragment D so index mainFragmentList.size()-2. Now the user can continue to scroll right and will find fragment A.

Remember to implement FragmentStatePagerAdapter NOT FragmentPagerAdapter

Luigi F
  • 69
  • 5