Thursday, September 26, 2013

InfiniteViewPager - an infinite paging ViewPager

Hi,

a couple of months ago, I wrote an article about enabling infinite paging with the android ViewPager. In my opinion, the proposed solution was rather simple and hacky, since it only changed the text of each page. However with that approach, I finally found the time to do a custom ViewPager widget that enables the infinite paging feature with simple and complex page layouts rather than changing the text of the EditText widget. Here is a video showing the InfiniteViewPager in action.

Including the InfiniteViewPager

Binding the InfiniteViewPager into your application is not different than binding a regular ViewPager. You include it with your xml layout with the following:


<com.thehayro.view.InfiniteViewPager 
    android:id="@+id/infinite_viewpager"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"/>

Using the adapter

Like the regular ViewPager correspondents with its adapter class, the InfiniteViewPager also has its custom adapter called InfinitePagerAdapter. Before this is explained any further, I would like to give some understanding on how it works and what differs from a regular PagerAdapter implementation.
The main difference between a regular PagerAdapter (as we know) and the InfinitePagerAdapter are the number of pages. When implementing a PagerAdapter, one important method you have to implement is getCount(). With that, you tell the ViewPager how many pages you want. When implementing an InfinitePagerAdapter, setting the maximum number of pages is not necessary. The number of scrolling pages is indefinite. This leads to a certain consequence: how is it possible to differentiate one page from another? The regular ViewPager indicates its pages by its index. Methods like ViewPager.setCurrentItem(int index) help to switch to a certain page. For almost every use case, the page index indication is helpful for a finite space. But what about other indicators? For instance a string, where the indication is the alphabet or a concatenation of characters. How would integer index be mapped on a string datastructure or any other class that does not necessarily implement the Comparable interface? The InfinitePagerAdapter provides a solution to that issue. This is shown in the following code:

public abstract class InfinitePagerAdapter<T> extends PagerAdapter {

    /**
     * Standard constructor.
     * @param initValue the initial indicator value the ViewPager
     * should start with.
     */
    public InfinitePagerAdapter(T initValue);

    /**
     *
     * @return the next indicator.
     */
    public abstract T getNextIndicator();

    /**
     *
     * @return the previous indicator.
     */
    public abstract T getPreviousIndicator();

    /**
     * Instantiates a page.
     * @param indicator the indicator the page should be instantiated with.
     * @return a ViewGroup containing the page layout.
     */
    public abstract ViewGroup instantiateItem(T indicator);
}

The InfinitePagerAdapter gives the possibility to set an indicator type. Since the indicator can be any  datatype, it is necessary to implement the getNextIndicator() and getPreviousIndicator() Methods to define the next and previous indicator. This gives a certain flexibility towards the page indication. A simple implementation of the InfinitePagerAdapter can look like this:


public class MyInfinitePagerAdapter<Integer> extends InfinitePagerAdapter {


    public Integer getNextIndicator() {
        // getCurrentIndicator is a protected method.
        return getCurrentIndicator() + 1;
    }


    public Integer getPreviousIndicator() {
        // getCurrentIndicator is a protected method.
        return getCurrentIndicator() - 1;
    }

    public ViewGroup instantiateItem(Integer indicator) {
        // space for rent
        return null;
    }
}

And instantiate it with something like this:
// 0 is the initial type
MyInfinitePagerAdapter<Integer> myAdapter = new MyInfinitePagerAdapter<Integer>(0);

Restoring states on device rotation

The above listed code is the minimum required implementations a developer has to provide in order to use the InfiniteViewPager. However, this has a certain limitation: rotating the device shows the initial page and the current page is lost, due to android's layout reinitialization. This can be solved by furthermore overriding two methods:

String getStringRepresentation(final T currentIndicator);


T convertToIndicator(final String representation);


The first method converts the current indicator into a string representation, and the second does the opposite. These methods provide the InfiniteViewPager to restore its state when the device is rotated.

Binding in your project

You can bind the InfiniteViewPager with maven:

        <dependency>
            <groupId>com.thehayro</groupId>
            <artifactId>infiniteviewpager</artifactId>
            <version>0.3</version>
            <type>apklib</type>
        </dependency>

The code can be found here.

No comments:

Post a Comment