Source code for an Android ViewPager example (Activity and Fragment)

Summary: In this tutorial I share some source code for an Android ViewPager example.

Note: I wrote this tutorial when I was first learning Android. It relies on some code from the excellent book, Android Programming. Therefore it’s not a great standalone tutorial, but I hope it’s helpful if you need to see another example that uses that book’s code.

This is a little unusual for me, but I'm putting the following code here so I can remember how I implement a ViewPager in my current Android application. I want to put this code out here in its current state before it gets more complicated. In fact, I only wish I had copied it out here earlier, before I made it as complicated as it is.

The only things that are important to know are:

  • When the ImagePagerActivity is called it's given an extra that tells it which image it should show first
  • I haven't fully implement the "delete" code in the fragment

If you're familiar with Android, hopefully everything else will make sense.

ImagePagerActivity class

My first class is named ImagePagerActivity.java, and here is its code:

package com.alvinalexander.mycoolapp;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;

/**
 * This activity is started by the Image Grid View Activity, and that activity
 * should tell us which image to show first, i.e., the image the user tapped on.
 */
public class ImagePagerActivity extends FragmentActivity {

    private static final String TAG = "AAImagePagerActivity";
    ViewPager mViewPager;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mViewPager = new ViewPager(this);
        mViewPager.setId(R.id.viewPager);
        setContentView(mViewPager);

        final int numGalleryItems = ImagesDao.getImageCount(this.getBaseContext());
        FragmentManager fm = getSupportFragmentManager();
        mViewPager.setAdapter(new FragmentStatePagerAdapter(fm) {
            @Override
            public int getCount() {
                return numGalleryItems;
            }
            @Override
            public Fragment getItem(int position) {
                return ImagePagerFragment.newInstance(position);
            }
        });

        // important: `setCurrentItem(pos)` needs to be here, after the adapter is set
        Bundle extras = getIntent().getExtras();
        final int startingPositionWeWereGiven = extras.getInt(ImagePagerFragment.SELECTED_IMAGE_POSITION);
        mViewPager.setCurrentItem(startingPositionWeWereGiven);

    }
}

ImagePagerFragment class

My first class is named ImagePagerFragment.java_, and here is its code:

package com.alvinalexander.mycoolapp;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.Toast;

import com.alvinalexander.mycoolapp.utils.FileUtils;

import java.io.IOException;

public class ImagePagerFragment extends Fragment {

    private static final String TAG = "AAImagePagerFragment";
    public static final String GALLERY_ITEM_ID_KEY     = "GALLERY_ITEM_ID_KEY";
    public static final String SELECTED_IMAGE_POSITION = "SELECTED_IMAGE_POSITION";

    private Bitmap currentImage;
    private int currentPosition = 0;

    public static ImagePagerFragment newInstance(int imageNumberToShow) {
        Bundle args = new Bundle();
        args.putSerializable(GALLERY_ITEM_ID_KEY, imageNumberToShow);

        ImagePagerFragment fragment = new ImagePagerFragment();
        fragment.setArguments(args);

        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
        
        int position = (Integer)getArguments().getSerializable(GALLERY_ITEM_ID_KEY);
        currentPosition = position;
        currentImage = ImagesDao.getImage(this.getActivity().getBaseContext(), currentPosition);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
        getActivity().getActionBar().setDisplayHomeAsUpEnabled(true);
        View rootView = inflater.inflate(R.layout.fragment_single_image, parent, false);
        ImageView imageView = (ImageView)rootView.findViewById(R.id.currentImage);
        imageView.setImageBitmap(currentImage);
        return rootView;
    }

    /**
     * the menu layout has the 'add/new' menu item
     */
    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
        menuInflater.inflate(R.menu.menu_image_detail, menu);
        super.onCreateOptionsMenu(menu, menuInflater);
    }

    /**
     * react to the user tapping the back/up icon
     */
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                // this takes the user 'back', as if they pressed the left-facing icon on the main android toolbar.
                // if this doesn't work, another possibility is to call `finish()` here.
                getActivity().onBackPressed();
                return true;
            case R.id.menu_item_delete_image:
                final String imageFilename = ImagesDao.getImageFilename(this.getActivity().getBaseContext(), currentPosition);
                handleDeleteImageProcess(imageFilename);
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    private void handleDeleteImageProcess(final String imageFilename) {
        DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                switch (which){
                    case DialogInterface.BUTTON_POSITIVE:
                        try {
                            String rootDir = FileUtils.getImagesDir(getActivity());
                            boolean fileWasDeleted = FileUtils.deleteFile(rootDir + "/" + imageFilename);
                            if (fileWasDeleted) {
                                Toast.makeText(getActivity(), "DELETE", Toast.LENGTH_SHORT).show();
                            }
                        } catch (IOException ioe) {
                            // TODO let the user know the file couldn't be deleted
                        }
                        break;
                    case DialogInterface.BUTTON_NEGATIVE:
                        break;
                }
            }
        };
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setMessage("Delete this image?")
                .setPositiveButton("Yes", dialogClickListener)
                .setNegativeButton("No", dialogClickListener).show();
    }

}

As mentioned, the "delete" code hasn't been fully implemented yet. The code will show an "Are you sure?" dialog when you click the garbage can icon in the ViewPager, but that's all it does at the moment.

I start the ViewPage with an Intent

As a final note, my activity is started with an Intent like this:

Intent i = new Intent(getActivity(), ImagePagerActivity.class);
i.putExtra(ImagePagerFragment.SELECTED_IMAGE_POSITION, position);
startActivityForResult(i, 0);

Again, it's a little unusual for me to share code out here without explaining it, but if you wanted to have an idea of how to implement a ViewPager in Android, I hope this code can help to serve as a little bit of a starting point. (If/when I ever get some more free time I'll try to explain this a little more, but don't count on that.)