17

There is one use-case of ViewPager I've never seen pretty implemented.

ViewPager is more or less static structure. It's not so hard to add Pages to the right side (appending to Model and displaying it), however, there should be nice-to-use solution to expand PagerAdapter (or some of it's subclasses) so it can expand in both directions.

I can imagine interface for Adapter like this

boolean isEmpty()
boolean hasNext()
boolean hasPrevious()
Object  getNext()
Object  getPrevious()
Object  getItem(int position)

// or if using generics
T       getNext()
T       getPrevious()
T       getItem(int position)

Similar to Collections Iterator, but both-directional.

Where index/position is not limited from below on 0, but can use whole range of Integer type.
Maybe not base the implementation on array (which is 0 to infinite).

I've found this "hack": dynamically add and remove view to viewpager
But as I stated before, I'm trying to get it working naturally, not maintaining 3,5,... items and force ViewPager to change current position based on some twisted logic

Is there currently any sufficient implementation or is it necessary to implement it?
I'm willing to bounty reward answer, if it will be a whole new implementation.

Community
  • 1
  • 1
Marek Sebera
  • 37,155
  • 34
  • 153
  • 231
  • We can Add any number of views in ViewPager.. And I have implemented the same in one of my apps. Take a look at @FoamyGuy Simple demo of ViewPager, in which we can have unlimited number of pages https://github.com/FoamyGuy/MathFactCards – Pragnani May 16 '13 at 09:41
  • @Pragnani but you're expanding only in right-direction, I'm trying to get in both directions dynamically, without hacks. – Marek Sebera May 16 '13 at 09:42
  • @Pragnani you can add unlimited pages but only in 1 direction.I think his question is different. – TheFlash May 16 '13 at 09:42
  • @MarekSebera Found it lately... – Pragnani May 16 '13 at 09:45
  • I wonder how Google Calendar is implented? It feels as an unlimited view pager, as you can keep going to the left and to the right scrolling through the days. – Aleks G May 21 '13 at 08:55
  • This is not a problem, just put MAX_INT elements and set current position in the middle. This looks like infinity scrollable pager, but question is not about it. Author wants "more elegant" solution. – Michał Z. May 21 '13 at 08:58
  • @MichałZ. that's what I'm trying to avoid, as it is dirty hack – Marek Sebera May 21 '13 at 09:05
  • @AleksG good point, investigate and maybe come up with answer? :-) – Marek Sebera May 21 '13 at 09:06
  • I just had a look at the DayView.java code from Android Calendar - apparently, they are not using ViewPager but instead manage scrolling manually. So much for that idea. – Aleks G May 21 '13 at 09:17
  • It's not that bad, I think that I saw @Romain Guy's post somewhere in which he adviced this solution. But I understand that you want to have a more elegant solution. So IMO the only way is to extend ViewPager and add it. – Michał Z. May 21 '13 at 09:23

2 Answers2

10

Will this help,

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 1:
            return Fragment1.newInstance();
            case 2:
            return Fragment2.newInstance();
            case 3:
            return Fragment3.newInstance();
        }
    }
}

and then,

mPager.setCurrentItem((int)(Integer.MAX_VALUE/2)); // assuming mPager is your ViewPager

Sagar Waghmare
  • 4,800
  • 1
  • 17
  • 21
  • 1
    This will help somehow, thanks, but still it seems to me like weird solution. – Marek Sebera May 28 '13 at 08:27
  • 4
    It won't work with a FragmentStatePagerAdapter as it will need to compute each fragment. and result in a memory overflow – Hrk May 04 '15 at 11:26
2

Using negative position values stands very far from natural order of ViewPager usage and is not the Adapter issue at all. Please have a look into the source code of ViewPager in the support package source in Android SDK. For example, here is a setCurrentItemInternal private implementation:

void setCurrentItemInternal(int item, boolean smoothScroll, boolean always, int velocity) {
    if (mAdapter == null || mAdapter.getCount() <= 0) {
        setScrollingCacheEnabled(false);
        return;
    }
    if (!always && mCurItem == item && mItems.size() != 0) {
        setScrollingCacheEnabled(false);
        return;
    }

    if (item < 0) {
        item = 0;
    } else if (item >= mAdapter.getCount()) {
        item = mAdapter.getCount() - 1;
    }
    final int pageLimit = mOffscreenPageLimit;
    if (item > (mCurItem + pageLimit) || item < (mCurItem - pageLimit)) {
        // We are doing a jump by more than one page.  To avoid
        // glitches, we want to keep all current pages in the view
        // until the scroll ends.
        for (int i=0; i<mItems.size(); i++) {
            mItems.get(i).scrolling = true;
        }
    }
    final boolean dispatchSelected = mCurItem != item;
    populate(item);
    scrollToItem(item, smoothScroll, velocity, dispatchSelected);
}

As you can see, ViewPager explicitly assumes no negative position values.

alexei burmistrov
  • 1,387
  • 8
  • 13
  • And what is conclusion? I didn't want to use negative indexes. I need to walk-through collection in both directions unlimited, based on my custom Model. I said directly, that the solution should be probably not based on Array, as we would have to deal with negative indexes. – Marek Sebera May 21 '13 at 10:42
  • You wrote: "Where index/position is not limited from below on 0, but can use whole range of Integer type." Where do you want to use these indexes? If in get/set current page or onChange handler, then the problem above arises. If the negative indexes are not visible to ViewPager, what is the meaning of *having* such an index? Please elaborate... – alexei burmistrov May 21 '13 at 10:53
  • I was talking about range of possible elements, in the interface outline I don't need indexes, but I need to expand the collection dynamically in both directions. So that calling getPreviousItem doesn't end up on Element(0) but depends on some other condition, implemented in custom Model. – Marek Sebera May 21 '13 at 11:08
  • So, if I understand correctly, the question could be reduced to extendig ordinary List with getModelPostion(item) method and extending List.add with the code, updating positon-modelPosition mapping. Am I right? – alexei burmistrov May 21 '13 at 11:25
  • I don't think you're right, get in touch on marek.sebera@gmail.com, I'll try to elaborate more, but here is no place for such discussion. – Marek Sebera May 21 '13 at 11:38
  • 1
    You can make it circular in both direction and make an effect like there are unlimited pages . Meanwhile change the content of the view pager on the next or previous circulation slots, like for first 5 pages content will be something , for next 5 content get changes , for last 5 content get changes from history , you have to maintain a history for each slot (5 pages) . – kaushal trivedi May 21 '13 at 11:51
  • @kaushaltrivedi oh that is something probably worth trying, can you add it as an aswer with example? Thanks – Marek Sebera May 25 '13 at 08:59