Mobile
Article

Using ViewPager to Create a Sliding Screen UI in Android

By Abbas Suterwala

Android provides many UI controls to create beautiful UI screens for your apps. One common UI requirement is sliding between multiple screens. For example, a photo slideshow. Android provides a UI control for creating sliding screens called the ViewPager. This tutorial will explain using ViewPager to create a sliding screen UI in your Android apps.

You can find the code for this article on GitHub

Adding the View Pager to Your Activity

Create a new Blank Activity project and begin by adding a ViewPager to the activity. Like any other UI control, you define the ViewPager in a layout file. Change activity_main.xml to the following:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <android.support.v4.view.ViewPager
        android:id="@+id/vpPager"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <android.support.v4.view.PagerTabStrip
            android:id="@+id/pager_header"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="top"
            />
    </android.support.v4.view.ViewPager>
</LinearLayout>

In the above layout, there is a LinearLayout containing a ViewPager with an id of “vpPage”. There’s also a nested view called PagerTabStrip which indicates the tabs at the top of the screen depending on the number of pages in the ViewPager. Once you have created the layout, update MainActivity.java to use this layout as follows:

package com.viewpagerandroid; // Update to match your package

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ViewPager vpPager = (ViewPager) findViewById(R.id.vpPager);
    }
}

In the above code I is a MainActivity which sets the layout created as its content view. Then it queries for a reference of the ViewPager using the function findViewById.

Creating the Fragments for the ViewPager

You need to define each screen in the ViewPager as a fragment. Each screen could be an instance of different Fragment classes, or different instances of the same fragment class with varying content. This app will contain three screens. Two screens with one text field and one image, and one screen with one text field and two images. Based on this, you will need two fragment classes.

The layouts and fragments classes are as follows:

fragment_one_img.xml

<?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">

    <TextView
        android:id="@+id/txtMain"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <ImageView
        android:id="@+id/imgMain"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

FragmentWithOneImage.java

package com.viewpagerandroid;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

public class FragmentWithOneImage extends Fragment {
    private String title;
    private int image;

    public static FragmentWithOneImage newInstance(String title, int resImage) {
        FragmentWithOneImage fragment = new FragmentWithOneImage();
        Bundle args = new Bundle();
        args.putInt("image", resImage);
        args.putString("title", title);
        fragment.setArguments(args);
        return fragment;
    }


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        image = getArguments().getInt("image", 0);
        title = getArguments().getString("title");
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_one_img, container, false);
        TextView tvLabel = (TextView) view.findViewById(R.id.txtMain);
        tvLabel.setText(title);

        ImageView imageView = (ImageView) view.findViewById(R.id.imgMain);
        imageView.setImageResource(image);
        return view;
    }
}

fragment_two_images.xml

<?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">

    <TextView
        android:id="@+id/txtMain"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <ImageView
        android:id="@+id/imgMain"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <ImageView
        android:id="@+id/imgSecondary"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

FragmentWithTwoImages.java

package com.viewpagerandroid;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

public class FragmentWithTwoImages extends Fragment {
    private String title;
    private int imageMain;
    private int imageSecondary;


    public static FragmentWithTwoImages newInstance(String title, int resMainImage, int resSecondaryImage) {
        FragmentWithTwoImages fragment = new FragmentWithTwoImages();
        Bundle args = new Bundle();
        args.putInt("imageMain", resMainImage);
        args.putInt("imageSecondary", resSecondaryImage);
        args.putString("title", title);
        fragment.setArguments(args);
        return fragment;
    }


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        imageMain = getArguments().getInt("imageMain", 0);
        imageSecondary = getArguments().getInt("imageSecondary", 0);
        title = getArguments().getString("title");
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_two_images, container, false);
        TextView tvLabel = (TextView) view.findViewById(R.id.txtMain);
        tvLabel.setText(title);

        ImageView imageView = (ImageView) view.findViewById(R.id.imgMain);
        imageView.setImageResource(imageMain);

        ImageView imageViewSecondary = (ImageView) view.findViewById(R.id.imgSecondary);
        imageViewSecondary.setImageResource(imageSecondary);
        return view;
    }
}

In the above code FragmentWithOneImage, has a getInstance method which takes the text and the image resource id displayed in the fragment. The fragment inflates the fragment_one_img.xml layout and sets the text and the image resource id. Similarly FragmentWithTwoImages inflates the fragment_two_images.xml layout and sets the text and both the image resource ids.

Implementing the PagerAdapter

Now you’ve created the fragments you need a PagerAdapter which you will set on the ViewPager. Although you can directly extend from PagerAdapter, Android provides another base class FragmentPagerAdapter which implements basic functionality to show the fragments as pages in the PagerAdapter.

Extend the adapter from FragmentPagerAdapter by adding this class to MainActivity.java:

public static class MyPagerAdapter extends FragmentPagerAdapter {
    private static int NUM_ITEMS = 3;

    public MyPagerAdapter(FragmentManager fragmentManager) {
        super(fragmentManager);
    }

    // Returns total number of pages.
    @Override
    public int getCount() {
        return NUM_ITEMS;
    }

    // Returns the fragment to display for a particular page.
    @Override
    public Fragment getItem(int position) {
        switch (position) {
            case 0:
                return FragmentWithOneImage.newInstance("Fragment 1", R.drawable.android_1);
            case 1:
                return FragmentWithOneImage.newInstance("Fragment 2", R.drawable.android_2);
            case 2:
                return FragmentWithTwoImages.newInstance("Fragment 3", R.drawable.android_3, R.drawable.android_4);
            default:
                return null;
        }
    }

    // Returns the page title for the top indicator
    @Override
    public CharSequence getPageTitle(int position) {
        return "Tab " + position;
    }

}

Note: You will need to add the images referenced above. You can find them here.

The MyPagerAdapter class extends from FragmentPagerAdapter and overrides the getCount method which returns how many pages the adapter will display. In this example, you want to show three pages, and it returns three. The getItem method returns the instance of the fragment to display on the screen. The getPageTitle method returns the title of the particular page. Once you have created the MyPagerAdapter you need to set the instance of it on the ViewPager in the onCreate function as below:

FragmentPagerAdapter adapterViewPager;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    ViewPager vpPager = (ViewPager) findViewById(R.id.vpPager);
    adapterViewPager = new MyPagerAdapter(getSupportFragmentManager());
    vpPager.setAdapter(adapterViewPager);
  }

If you run the app you will see the three screens which you can be slide between as shown below.

Screen 1

Screen 2

Screen 3

Adding Animation to the Screen Slide

You can implement different animations on the page slide by setting a ViewPager.PageTransformer. To implement this you have to override the transformPage method. In this function you provide custom animations based on the position on the screen, there are a lot of transforms available as open source libraries which you can use, for example the ToxicBakery.ViewPagerTransforms.

To use a custom animation, add it to your dependencies in build.gradle (Module: App) as follows:

dependencies {
  ...
  compile 'com.ToxicBakery.viewpager.transforms:view-pager-transforms:1.2.32@aar'
}

Now you can add the PageTransformer on the ViewPager in the onCreate method as shown:

@Override
protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_main);

   ViewPager vpPager = (ViewPager) findViewById(R.id.vpPager);
   adapterViewPager = new MyPagerAdapter(getSupportFragmentManager());
   vpPager.setAdapter(adapterViewPager);
   vpPager.setPageTransformer(true, new RotateUpTransformer());
}

Now if you run the app and slide the screens, they will rotate up while sliding.

The next Page

The ViewPager control provided by Android makes it easy to add flexible sliding screens to your app and gives you the power to add the same or different types of pages to your sliding screens.

Let me know if you have any comments or questions.

More:

Recommended

Learn Coding Online
Learn Web Development

Start learning web development and design for free with SitePoint Premium!

Get the latest in Mobile, once a week, for free.