Paul Brower bio photo

Paul Brower

Android development for fun and profit.

Email Twitter Github Stackoverflow Codementor

Find further code and implementation here: https://github.com/browep/AndroidViewPagerGalleryDemo

Summer 2011, the Android team released the ViewPager widget which encapsulates horizontal swiping. The widget is easy to use and has similar functionality to the pre-existing Gallery widget. A common pattern is the Gallery widget and the ViewPager working together in concert. When we swipe the ViewPager we want the gallery to scroll to the correct image, when we select an image in the gallery we want the ViewPager to scroll to the correct image. This tutorial will guide you through how to setup a simple ViewPager filled with images that coincides with a gallery that has thumbs of the images. A TextView with a title is thrown in there for good measure. Something like this:

Gallery ViewPager

ViewPager docs

The full source for the code below including sample images and require jars can be found at the github address at the top of the page. Lets create a simple UI:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent"
        >
    <FrameLayout android:layout_height="0px"
                 android:layout_width="fill_parent"
                 android:layout_weight="1"
            >
        <android.support.v4.view.ViewPager android:id="@+id/view_pager"
                                           android:layout_height="fill_parent"
                                           android:layout_width="fill_parent"
                                           android:padding="10dip"
                />
        <TextView android:layout_height="wrap_content"
                  android:layout_width="wrap_content"
                  android:layout_gravity="bottom|center_horizontal"
                  android:textColor="#FFF"
                  android:padding="8dip"
                  android:layout_margin="6dip"
                  android:background="#7775"
                  android:textSize="14pt"
                  android:id="@+id/title"
                />
    </FrameLayout>

    <Gallery android:id="@+id/gallery"
             android:layout_height="100dip"
             android:layout_width="fill_parent"
             android:spacing="4dip"
             />
</LinearLayout>

We have a simple LinearLayout with a ViewPager above a Gallery. The TextView floats over the bottom of the ViewPager.

Now lets create an activity for the layout file starting with the class declaration and the onCreate method:

public class Main extends FragmentActivity implements AdapterView.OnItemSelectedListener, ViewPager.OnPageChangeListener {

    private ViewPager viewPager;
    private Gallery gallery;

    protected Integer[] mImageIds = {
            R.drawable.sample_1,
            R.drawable.sample_2,
            R.drawable.sample_3,
            R.drawable.sample_4,
            R.drawable.sample_5,
            R.drawable.sample_6,
            R.drawable.sample_7
    };
    private TextView textView;
    private Handler handler;

    /**
     * Called when the activity is first created.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        viewPager = (ViewPager) findViewById(R.id.view_pager);
        viewPager.setAdapter(new MyAdapter(getSupportFragmentManager()));
        viewPager.setOnPageChangeListener(this);

        gallery = (Gallery) findViewById(R.id.gallery);
        gallery.setAdapter(new ImageAdapter());
        gallery.setOnItemSelectedListener(this);

        textView = (TextView) findViewById(R.id.title);

        handler = new Handler();

    }

We see that the activity implements “AdapterView.OnItemSelectedListener and ViewPager.OnPageChangeListener”. These are what the Gallery and ViewPager use to fire events respectively. We set them using

gallery.setOnItemSelectedListener(this);
viewPager.setOnPageChangeListener(this);

We also have a predefined list of image resource ids as a field. Next we need Adapter classes for filling the Gallery and the ViewPager. For the gallery we just need something simple to serve image resource ids:

public class ImageAdapter extends BaseAdapter {

        public int getCount() {
            return mImageIds.length;
        }

        public Object getItem(int position) {
            return position;
        }

        public long getItemId(int position) {
            return position;
        }

        public View getView(int position, View convertView, ViewGroup parent) {

            ImageView imageView = new ImageView(Main.this);

            imageView.setImageResource(mImageIds[position]);
            imageView.setLayoutParams(new Gallery.LayoutParams(150, 100));
            imageView.setScaleType(ImageView.ScaleType.FIT_XY);

            return imageView;
        }
    }

And for the ViewPager we are going to use a FragmentPagerAdapter. Don’t worry if you are unsure about Fragments we don’t need in depth knowledge for this tutorial. The fragment creates a View during onCreateView, so we override that in an Anonymous inner class to return an ImageView.

public class MyAdapter extends FragmentPagerAdapter {
        public MyAdapter(FragmentManager fm) {
            super(fm);
        }

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

        @Override
        public Fragment getItem(final int position) {
            return new Fragment() {
                @Override
                public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
                    ImageView imageView = new ImageView(Main.this);
                    imageView.setImageResource(mImageIds[position]);
                    return imageView;
                }
            };
        }
    }

Now let’s tie the interaction together. When someone selects a Gallery item we want to update the ViewPager and TextView and vice-versa.

// gallery item selected
    public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
        updateUI(i);
    }

    // view pager item selected
    public void onPageSelected(int i) {
        updateUI(i);
    }

    private void updateUI(final int i) {
        handler.post(new Runnable() {
            public void run() {
                gallery.setSelection(i);
                viewPager.setCurrentItem(i);
                textView.setText("Photo #" + i);
            }
        });
    }

    // methods we dont need right now but are required to implement the interfaces
    public void onNothingSelected(AdapterView<?> adapterView) {    }

    public void onPageScrolled(int i, float v, int i1) {    }

    public void onPageScrollStateChanged(int i) {    }

When a gallery item or a view pager item is selected, all other widgets are updated in “updateUI”. The setting is done in a Handler.post so that the UI thread can continue working on the widget that was selected. That’s the simplest way to get them working together. See the above github link for a full Android project.