Android Image Slideshow using ViewPager with PagerAdapter

We’ve already discussed ViewPager in depth in one of my earlier posts. We saw how to use it with specific PagerAdapter implementations like FragmentPagerAdapter and FragmentStatePagerAdapter that works with fragments but we can also use it to inflate any other View or ViewGroup (with standard View hierarchy) by hooking it up with PagerAdapter itself. In this tutorial we’ll just discuss how to how to hook a PagerAdapter to a ViewPager to create an Image slideshow.

Setting Up

Firstly, we’ll need to have a ViewPager element in our layout file at res/layout/activity_main.xml:

What's the one thing every developer wants? More screens! Enhance your coding experience with an external monitor to increase screen real estate.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:id="@+id/relativeLayout">


    <android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </android.support.v4.view.ViewPager>

</RelativeLayout>

Next, in our onCreate() Activity method, we’ll instantiate our custom PagerAdapter implementation and bind it to our ViewPager object.

mCustomPagerAdapter = new CustomPagerAdapter(this);

mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mCustomPagerAdapter);

In our Activity class we’ll have a mResources instance variable that’ll contain an array of drawable resource IDs:

int[] mResources = {
        R.drawable.first,
        R.drawable.second,
        R.drawable.third,
        R.drawable.fourth,
        R.drawable.fifth,
        R.drawable.sixth
};

I downloaded six images from LoremPixel of size 400×600 and put them into the res/drawable directory. We’ll use these images in our carousel.

Finally it’s time to write our custom pager adapter implementation that’ll do the real job of populating content pages within our ViewPager:

class CustomPagerAdapter extends PagerAdapter {

    Context mContext;
    LayoutInflater mLayoutInflater;

    public CustomPagerAdapter(Context context) {
        mContext = context;
        mLayoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    @Override
    public int getCount() {
        return mResources.length;
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view == ((LinearLayout) object);
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        View itemView = mLayoutInflater.inflate(R.layout.pager_item, container, false);

        ImageView imageView = (ImageView) itemView.findViewById(R.id.imageView);
        imageView.setImageResource(mResources[position]);

        container.addView(itemView);

        return itemView;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView((LinearLayout) object);
    }
}

Let’s discuss the four methods that we’ve overridden (mandatory):

  • getCount() – This method should return the number of views available, i.e., number of pages to be displayed/created in the ViewPager.
  • instantiateItem() – This method should create the page for the given position passed to it as an argument. In our case, we inflate() our layout resource to create the hierarchy of view objects and then set resource for the ImageView in it. Finally, the inflated view is added to the container (which should be the ViewPager) and return it as well.
  • destroyItem() – Removes the page from the container for the given position. We simply removed object using removeView() but could’ve also used removeViewAt() by passing it the position.
  • isViewFromObject() – The object returned by instantiateItem() is a key/identifier. This method checks whether the View passed to it (representing the page) is associated with that key or not. It is required by a PagerAdapter to function properly. For our example, the implementation of this method is really simple, we just compare the two instances and return the evaluated boolean.

Here’s how res/layout/pager_item.xml will look like which is inflated in the instantiateItem() method:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/imageView" />
</LinearLayout>

Now if you go and test your app in the emulator or a device, you’ll be able to play with a nice slideshow based on ViewPager with 6 pages each showing up an image from the drawable resources directory.

It is important to understand that as the user navigates to a particular page, the one next to it is generated by calling instantiateItem() while the one before the previous one gets destroyed by calling destroyItem(). This caching limit (destruction and rebuilding limit) can be specified by the setOffscreenPageLimit() method on the ViewPager object which is set to 1 by default. Increasing this value to a higher number leads to a smoother navigation as far as the animations and interactions are concerned as everything is retained in memory but then it can also cause a memory overhead affecting the app’s performance. So you’ve to find the perfect balance in your case.

Hope that helps!

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download

Author: Rishabh

Rishabh is a full stack web and mobile developer from India. Follow me on Twitter.

7 thoughts on “Android Image Slideshow using ViewPager with PagerAdapter”

  1. Hi,
    Rishabh your article is good . I want to have this image slider inside my tab swipable view .
    How can i implement that

    1. I guess this is how you’re implementing Swipeable Views. So in that case one of your fragments will need to implement what you’re doing in this post.

      This might lead to an issue though where you’ve a ViewPager inside another one hence which one should actually Swipe ? Although I haven’t tried doing this but you might want to understand the touch events system of Android to solve such issues. I’ve written a couple of related posts:

      http://codetheory.in/understanding-android-input-touch-events/
      http://codetheory.in/using-a-scrollable-viewgroup-in-a-scrollview/

      Hope that helps!

  2. Hey, its good article, i need bit help of you, can you tell me about videos slideshow, can i use viewpager for videos slide show.

    Thanks

  3. Great tutorial! One question: wouldn’t it be better to call LayoutInflater.from(container.getContext()).inflate(…)? that way you don’t have to keep the Context or the Layout inflater around.

    1. Is there any problem with keeping the LayoutInflater around ? I don’t think so. It’s just fine. Also this way you cache the layout inflater in a way rather than obtaining it every time by making a call to from() although it shouldn’t be much of a difference – see if this SO thread helps.

Leave a Reply

Your email address will not be published. Required fields are marked *