Unlimited/Dynamic ViewPager in both directions
Asked Answered
L

2

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.

Lane answered 16/5, 2013 at 9:35 Comment(10)
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 github.com/FoamyGuy/MathFactCardsFloyd
@Floyd but you're expanding only in right-direction, I'm trying to get in both directions dynamically, without hacks.Lane
@Floyd you can add unlimited pages but only in 1 direction.I think his question is different.Mycenae
@MarekSebera Found it lately...Floyd
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.Unbodied
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.Orvie
@MichałZ. that's what I'm trying to avoid, as it is dirty hackLane
@AleksG good point, investigate and maybe come up with answer? :-)Lane
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.Unbodied
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.Orvie
U
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

Umpteen answered 21/5, 2013 at 13:0 Comment(2)
This will help somehow, thanks, but still it seems to me like weird solution.Lane
It won't work with a FragmentStatePagerAdapter as it will need to compute each fragment. and result in a memory overflowPastoral
T
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.

Trichite answered 21/5, 2013 at 10:8 Comment(7)
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.Lane
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...Trichite
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.Lane
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?Trichite
I don't think you're right, get in touch on [email protected], I'll try to elaborate more, but here is no place for such discussion.Lane
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) .Antihalation
@kaushaltrivedi oh that is something probably worth trying, can you add it as an aswer with example? ThanksLane

© 2022 - 2024 — McMap. All rights reserved.