Android ViewPager2 Tutorial with Examples
1. Android ViewPager2 vs ViewPager
Android ViewPager is an interface component introduced in Android support library. It allows the user to swipe left or right to view a completely new page (screen).
ViewPager/ViewPager2
A ViewPager/ViewPager2 where each page fills the screen, which the user will swipe left to move to the next page, or swipe right to go back one page.
A ViewPager/ViewPager2 seen on Duolingo language learning app.
ViewPager2 vs ViewPager
As we all know, the Android team is constantly releasing new updates and improvements to the Android Framework. One of the components that received major updates is ViewPager2. ViewPager2 is the replacement of ViewPager and got few performance improvements and additional functionalities.
So what's new in ViewPager2?
- ViewPager2 is an improvised version of ViewPager that provides additional functionalities and addresses common issues faced in ViewPager.
- ViewPager2 is built on top of RecyclerView. So you will have great advantages that a RecyclerView has. For example, you can take advantage of DiffUtils to efficiently calculate the difference between data sets and update the ViewPager with animations.
- ViewPager2 supports vertical orientation. If you use ViewPager, you must write additional customizations for ViewPager to get the same results.
- ViewPager2 as Right-to-Left (RTL) support and this will be enabled automatically based on App Locale.
- When working with a set of Fragment(s). If one of the Fragment(s) changes its interface, you just need to call the notifyDatasetChanged() method to update the application's interface properly.
- ViewPager2 supports page transformations i.e you can provide animations when switching between pages. You can also write your own custom PageTransformer.
- PagerAdapter is replaced by RecyclerView.
- FragmentStatePagerAdapter is replaced by FragmentStateAdapter.
Library
ViewPager2 is a component which is not available in the standard library of Android, so if you want to use it, you have to install it into your project.
You can install ViewPager2 from the Palette of the design view.
After the complete installation, you see the ViewPager2 library be declared in build.gradle (Module: app).
implementation 'androidx.viewpager2:viewpager2:1.0.0'
2. Example: ViewPager2
Now we are practicing a example of ViewPager2 and using Fragment as a blueprint for each page. Here is the preview image of the example:
- The fragment_employee_page.xml file is an interface blueprint of a Page.
- EmployeePageFragment class contains data of the Employee object and displays them on one Page.
On Android Studio, create a project:
- File > New > New Project > Empty Activity
- Name: ViewPager2Example
- Package name: org.o7planning.viewpager2example
- Language: Java
As mentioned above, ViewPager2 is a component which is not available in the standard library of Android. Thus, in the next step, you need to install it into your project from the Palette of the design view.
Then create a Fragment (EmployeePageFragment) which is corresponding to one Page of ViewPager2:
- File > New > Fragment > Fragment (Blank)
- Fragment Name: EmployeePageFragment
- Fragment Layout Name: fragment_page_employee
- Source Language: Java
As you can see, two files are created:
Next, open the fragment_employee_page.xml file to design its interface.
fragment_employee_page.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView_fullName"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="30dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:background="#C4CFB9"
android:gravity="center_horizontal"
android:text="Fullname"
android:textSize="22sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView71"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="16dp"
android:text="Position:"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView_fullName" />
<TextView
android:id="@+id/textView_position"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:text="(Position)"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/textView71"
app:layout_constraintTop_toBottomOf="@+id/textView_fullName" />
<TextView
android:id="@+id/textView72"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="16dp"
android:text="Email:"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView71" />
<TextView
android:id="@+id/textView_email"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:text="(Email)"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/textView72"
app:layout_constraintTop_toBottomOf="@+id/textView71" />
</androidx.constraintlayout.widget.ConstraintLayout>
EmployeePageFragment.java
package org.o7planning.viewpager2example;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
public class EmployeePageFragment extends Fragment {
private static final String LOG_TAG = "AndroidExample";
private Employee employee;
private TextView textViewEmail;
private TextView textViewPosition;
private TextView textViewFullName;
private static int counter = 0;
// IMPORTANT:
// Required default public constructor.
// If configuration change.
// For example: User rotate the Phone,
// Android will create new Fragment (EmployeePageFragment) via default Constructor
// so this.employee will be null.
public EmployeePageFragment() {
}
public EmployeePageFragment(Employee employee) {
this.employee = employee;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = (ViewGroup) inflater.inflate(
R.layout.fragment_employee_page, container, false);
counter++;
if(counter % 2 == 0) {
view.setBackgroundColor(Color.parseColor("#ebdef0"));
} else {
view.setBackgroundColor(Color.parseColor("#e8f8f5"));
}
this.textViewFullName = view.findViewById(R.id.textView_fullName);
this.textViewPosition = view.findViewById(R.id.textView_position);
this.textViewEmail = view.findViewById(R.id.textView_email);
return view;
}
// Called when configuration change.
// For example: User rotate the Phone,
// Android will create new Fragment (EmployeePageFragment) object via default Constructor
// so this.employee will be null.
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
Log.i(LOG_TAG, "onSaveInstanceState: save employee data to Bundle");
// Convert employee object to Bundle.
Bundle dataBundle = this.employeeToBundle(this.employee);
outState.putAll(dataBundle);
super.onSaveInstanceState(outState);
}
@Override
public void onViewStateRestored(@Nullable Bundle savedInstanceState) {
Log.i(LOG_TAG, "onViewStateRestored");
super.onViewStateRestored(savedInstanceState);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
Log.i(LOG_TAG, "onViewCreated");
super.onViewCreated(view, savedInstanceState);
if(this.employee == null) {
Log.i(LOG_TAG, "Get employee data from savedInstanceState");
// The state was saved by onSaveInstanceState(Bundle outState) method.
this.employee = this.bundleToEmployee(savedInstanceState);
}
this.showInGUI(this.employee);
}
// Call where View ready.
private void showInGUI(Employee employee) {
this.textViewFullName.setText(employee.getFullName());
this.textViewPosition.setText(employee.getPosition());
this.textViewEmail.setText(employee.getEmail());
}
private Bundle employeeToBundle(Employee employee) {
Bundle bundle = new Bundle();
bundle.putString("fullName", employee.getFullName());
bundle.putString("position", employee.getPosition());
bundle.putString("email", employee.getEmail());
return bundle;
}
private Employee bundleToEmployee(Bundle savedInstanceState) {
String fullName = savedInstanceState.getString("fullName");
String position = savedInstanceState.getString("position");
String email = savedInstanceState.getString("email");
return new Employee(fullName, email, position);
}
}
EmployeeFragmentStateAdapter.java
package org.o7planning.viewpager2example;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import java.util.ArrayList;
import java.util.List;
public class EmployeeFragmentStateAdapter extends FragmentStateAdapter {
private List<Employee> employees;
public EmployeeFragmentStateAdapter(@NonNull FragmentActivity fragmentActivity) {
super(fragmentActivity);
this.employees = this.intDatas();
}
private List<Employee> intDatas() {
Employee emp1 = new Employee("James Smith", "jamessmith@example.com", "Web Designer");
Employee emp2 = new Employee("Elizabeth Johnson", "elizabethjohnson@example.com", "Project Manager");
Employee emp3 = new Employee("Catherine Johnson", "catherinejohnson@example.com", "President of Sales");
List<Employee> list = new ArrayList<Employee>();
list.add(emp1);
list.add(emp2);
list.add(emp3);
return list;
}
@NonNull
@Override
public Fragment createFragment(int position) {
Employee employee = this.employees.get(position);
return new EmployeePageFragment(employee);
}
@Override
public int getItemCount() {
return this.employees.size();
}
}
Employee.java
package org.o7planning.viewpager2example;
public class Employee {
private String fullName;
private String email;
private String position;
public Employee(String fullName, String email, String position) {
this.fullName = fullName;
this.email = email;
this.position = position;
}
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
}
This is the main interface of the application:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager2_employee"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.java
package org.o7planning.viewpager2example;
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager2.widget.ViewPager2;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
private ViewPager2 viewPager2Employee;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.viewPager2Employee = findViewById(R.id.viewPager2_employee);
// Employee FragmentStateAdapter.
EmployeeFragmentStateAdapter adapter = new EmployeeFragmentStateAdapter(this);
this.viewPager2Employee.setAdapter(adapter);
}
}
3. Example: Transformation
To show the animation effect when the user switches between pages, you need to write a class that implements the interface ViewPager2.PageTransformer and provides it for the ViewPager2 object.
ViewPager2 viewPager = findViewById(R.id.pager);
...
viewPager.setPageTransformer(new YourPageTransformer());
The interface ViewPager2.PageTransformer has only one transformPage() method which is called once for each transition.
/**
* Apply a property transformation to the given page.
*
* @param page Apply the transformation to this page
* @param position Position of page relative to the current front-and-center
* position of the pager. 0 is front and center. 1 is one full
* page position to the right, and -2 is two pages to the left.
* Minimum / maximum observed values depend on how many pages we keep
* attached, which depends on offscreenPageLimit.
*
* @see #setOffscreenPageLimit(int)
*/
void transformPage(@NonNull View page, float position);
Let's keep going with the example above, we are now adding animation effects to it.
Zoom Out Page Transformer
ZoomOutPageTransformer.java
package org.o7planning.viewpager2example.transformer;
import android.view.View;
import androidx.viewpager2.widget.ViewPager2;
public class ZoomOutPageTransformer implements ViewPager2.PageTransformer {
private static final float MIN_SCALE = 0.85f;
private static final float MIN_ALPHA = 0.5f;
public void transformPage(View view, float position) {
int pageWidth = view.getWidth();
int pageHeight = view.getHeight();
if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left.
view.setAlpha(0f);
} else if (position <= 1) { // [-1,1]
// Modify the default slide transition to shrink the page as well
float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));
float vertMargin = pageHeight * (1 - scaleFactor) / 2;
float horzMargin = pageWidth * (1 - scaleFactor) / 2;
if (position < 0) {
view.setTranslationX(horzMargin - vertMargin / 2);
} else {
view.setTranslationX(-horzMargin + vertMargin / 2);
}
// Scale the page down (between MIN_SCALE and 1)
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
// Fade the page relative to its size.
view.setAlpha(MIN_ALPHA +
(scaleFactor - MIN_SCALE) /
(1 - MIN_SCALE) * (1 - MIN_ALPHA));
} else { // (1,+Infinity]
// This page is way off-screen to the right.
view.setAlpha(0f);
}
}
}
MainActivity.java (Zoom Out Page Transformer)
package org.o7planning.viewpager2example;
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager2.widget.ViewPager2;
import android.os.Bundle;
import org.o7planning.viewpager2example.transformer.ZoomOutPageTransformer;
public class MainActivity extends AppCompatActivity {
private ViewPager2 viewPager2Employee;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.viewPager2Employee = findViewById(R.id.viewPager2_employee);
// Employee FragmentStateAdapter.
EmployeeFragmentStateAdapter adapter = new EmployeeFragmentStateAdapter(this);
this.viewPager2Employee.setAdapter(adapter);
// PageTransformer
this.viewPager2Employee.setPageTransformer(new ZoomOutPageTransformer());
}
}
Depth Page Transformer
DepthPageTransformer.java
package org.o7planning.viewpager2example.transformer;
import android.view.View;
import androidx.annotation.RequiresApi;
import androidx.viewpager2.widget.ViewPager2;
@RequiresApi(21)
public class DepthPageTransformer implements ViewPager2.PageTransformer {
private static final float MIN_SCALE = 0.75f;
public void transformPage(View view, float position) {
int pageWidth = view.getWidth();
if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left.
view.setAlpha(0f);
} else if (position <= 0) { // [-1,0]
// Use the default slide transition when moving to the left page
view.setAlpha(1f);
view.setTranslationX(0f);
view.setTranslationZ(0f);
view.setScaleX(1f);
view.setScaleY(1f);
} else if (position <= 1) { // (0,1]
// Fade the page out.
view.setAlpha(1 - position);
// Counteract the default slide transition
view.setTranslationX(pageWidth * -position);
// Move it behind the left page
view.setTranslationZ(-1f);
// Scale the page down (between MIN_SCALE and 1)
float scaleFactor = MIN_SCALE
+ (1 - MIN_SCALE) * (1 - Math.abs(position));
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
} else { // (1,+Infinity]
// This page is way off-screen to the right.
view.setAlpha(0f);
}
}
}
MainActivity.java (Depth Page Transformer)
package org.o7planning.viewpager2example;
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager2.widget.ViewPager2;
import android.os.Build;
import android.os.Bundle;
import org.o7planning.viewpager2example.transformer.DepthPageTransformer;
public class MainActivity extends AppCompatActivity {
private ViewPager2 viewPager2Employee;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.viewPager2Employee = findViewById(R.id.viewPager2_employee);
// Employee FragmentStateAdapter.
EmployeeFragmentStateAdapter adapter = new EmployeeFragmentStateAdapter(this);
this.viewPager2Employee.setAdapter(adapter);
// PageTransformer
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { // Api 21+.
this.viewPager2Employee.setPageTransformer(new DepthPageTransformer());
}
}
}
Android Programming Tutorials
- Configure Android Emulator in Android Studio
- Android ToggleButton Tutorial with Examples
- Create a simple File Finder Dialog in Android
- Android TimePickerDialog Tutorial with Examples
- Android DatePickerDialog Tutorial with Examples
- What is needed to get started with Android?
- Install Android Studio on Windows
- Install Intel® HAXM for Android Studio
- Android AsyncTask Tutorial with Examples
- Android AsyncTaskLoader Tutorial with Examples
- Android Tutorial for Beginners - Basic examples
- How to know the phone number of Android Emulator and change it
- Android TextInputLayout Tutorial with Examples
- Android CardView Tutorial with Examples
- Android ViewPager2 Tutorial with Examples
- Get Phone Number in Android using TelephonyManager
- Android Phone Call Tutorial with Examples
- Android Wifi Scanning Tutorial with Examples
- Android 2D Game Tutorial for Beginners
- Android DialogFragment Tutorial with Examples
- Android CharacterPickerDialog Tutorial with Examples
- Android Tutorial for Beginners - Hello Android
- Using Android Device File Explorer
- Enable USB Debugging on Android Device
- Android UI Layouts Tutorial with Examples
- Android SMS Tutorial with Examples
- Android SQLite Database Tutorial with Examples
- Google Maps Android API Tutorial with Examples
- Android Text to Speech Tutorial with Examples
- Android Space Tutorial with Examples
- Android Toast Tutorial with Examples
- Create a custom Android Toast
- Android SnackBar Tutorial with Examples
- Android TextView Tutorial with Examples
- Android TextClock Tutorial with Examples
- Android EditText Tutorial with Examples
- Android TextWatcher Tutorial with Examples
- Format Credit Card Number with Android TextWatcher
- Android Clipboard Tutorial with Examples
- Create a simple File Chooser in Android
- Android AutoCompleteTextView and MultiAutoCompleteTextView Tutorial with Examples
- Android ImageView Tutorial with Examples
- Android ImageSwitcher Tutorial with Examples
- Android ScrollView and HorizontalScrollView Tutorial with Examples
- Android WebView Tutorial with Examples
- Android SeekBar Tutorial with Examples
- Android Dialog Tutorial with Examples
- Android AlertDialog Tutorial with Examples
- Android RatingBar Tutorial with Examples
- Android ProgressBar Tutorial with Examples
- Android Spinner Tutorial with Examples
- Android Button Tutorial with Examples
- Android Switch Tutorial with Examples
- Android ImageButton Tutorial with Examples
- Android FloatingActionButton Tutorial with Examples
- Android CheckBox Tutorial with Examples
- Android RadioGroup and RadioButton Tutorial with Examples
- Android Chip and ChipGroup Tutorial with Examples
- Using image assets and icon assets of Android Studio
- Setting SD Card for Android Emulator
- ChipGroup and Chip Entry Example
- How to add external libraries to Android Project in Android Studio?
- How to disable the permissions already granted to the Android application?
- How to remove applications from Android Emulator?
- Android LinearLayout Tutorial with Examples
- Android TableLayout Tutorial with Examples
- Android FrameLayout Tutorial with Examples
- Android QuickContactBadge Tutorial with Examples
- Android StackView Tutorial with Examples
- Android Camera Tutorial with Examples
- Android MediaPlayer Tutorial with Examples
- Android VideoView Tutorial with Examples
- Playing Sound effects in Android with SoundPool
- Android Networking Tutorial with Examples
- Android JSON Parser Tutorial with Examples
- Android SharedPreferences Tutorial with Examples
- Android Internal Storage Tutorial with Examples
- Android External Storage Tutorial with Examples
- Android Intents Tutorial with Examples
- Example of an explicit Android Intent, calling another Intent
- Example of implicit Android Intent, open a URL, send an email
- Android Services Tutorial with Examples
- Android Notifications Tutorial with Examples
- Android DatePicker Tutorial with Examples
- Android TimePicker Tutorial with Examples
- Android Chronometer Tutorial with Examples
- Android OptionMenu Tutorial with Examples
- Android ContextMenu Tutorial with Examples
- Android PopupMenu Tutorial with Examples
- Android Fragments Tutorial with Examples
- Android ListView Tutorial with Examples
- Android ListView with Checkbox using ArrayAdapter
- Android GridView Tutorial with Examples
Show More