Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unlimited/Dynamic ViewPager in both directions

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.

like image 572
Marek Sebera Avatar asked May 16 '13 09:05

Marek Sebera


2 Answers

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

like image 94
Sagar Waghmare Avatar answered Nov 13 '22 22:11

Sagar Waghmare


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.

like image 20
alexei burmistrov Avatar answered Nov 13 '22 22:11

alexei burmistrov