Android
ViewPager
setOnPageChangeListener
Deprecated
ViewPager2

viewpager setonpagechangelistener deprecated

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

setOnPageChangeListener was deprecated in the original ViewPager API and replaced with listener registration methods that support multiple callbacks. If your code still uses the old method, migration is straightforward and improves compatibility with modern Android components. For new development, ViewPager2 is generally recommended.

Why the Old Method Was Deprecated

The deprecated method supported only one listener assignment and led to accidental listener replacement in larger codebases. The replacement API allows add and remove operations with clearer lifecycle control.

Old style:

kotlin
1viewPager.setOnPageChangeListener(object : ViewPager.OnPageChangeListener {
2    override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
3    override fun onPageSelected(position: Int) {}
4    override fun onPageScrollStateChanged(state: Int) {}
5})

Correct Replacement in ViewPager

Use addOnPageChangeListener.

kotlin
1val listener = object : ViewPager.OnPageChangeListener {
2    override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
3    }
4
5    override fun onPageSelected(position: Int) {
6        // react to selected page
7    }
8
9    override fun onPageScrollStateChanged(state: Int) {
10    }
11}
12
13viewPager.addOnPageChangeListener(listener)

This supports multiple listeners and cleaner decoupling.

Removing Listener to Prevent Leaks

If listener references UI objects, remove it when view lifecycle ends.

kotlin
1override fun onDestroyView() {
2    super.onDestroyView()
3    viewPager.removeOnPageChangeListener(listener)
4}

Lifecycle cleanup is especially important in fragments with view binding.

Migrating to ViewPager2

ViewPager2 uses a callback-based API.

kotlin
1val callback = object : ViewPager2.OnPageChangeCallback() {
2    override fun onPageSelected(position: Int) {
3        // update tabs or state
4    }
5}
6
7viewPager2.registerOnPageChangeCallback(callback)

Unregister in lifecycle cleanup:

kotlin
1override fun onDestroyView() {
2    super.onDestroyView()
3    viewPager2.unregisterOnPageChangeCallback(callback)
4}

ViewPager2 is built on RecyclerView and works better with modern architecture.

TabLayout Integration Notes

When using TabLayoutMediator with ViewPager2, manual page listeners are often still useful for analytics or secondary UI updates. Keep responsibilities clear so tab synchronization and custom logic do not conflict.

If you only need tab synchronization, mediator may already handle most behavior without extra callback code.

Testing Listener Migration

After migration:

  • verify page change callbacks still fire
  • check no duplicate callbacks from multiple registrations
  • confirm cleanup on configuration changes

UI tests with swipe gestures and tab clicks can catch registration mistakes quickly.

Migration Strategy for Legacy Screens

If your app still has many legacy ViewPager screens, migrate incrementally. Start by replacing deprecated listener registration first, then move adapters and fragment state handling in a second step. Splitting migration reduces risk because callback behavior can be verified independently from adapter refactors.

For teams moving to ViewPager2, create a shared wrapper utility for page callbacks so analytics and logging hooks stay consistent across old and new screens during transition.

Add regression tests around orientation changes and fragment restoration after migration, since callback registration bugs often surface only during lifecycle transitions rather than simple swipe interactions.

Document one callback-registration pattern for your team so all screens handle listener setup and teardown consistently.

If analytics are tied to page selection events, verify event counts before and after migration. Duplicate listener registration can silently inflate metrics and lead to incorrect product decisions unless callback lifecycles are tested explicitly.

Common Pitfalls

  • Replacing deprecated method with add registration but forgetting to remove callbacks in fragment lifecycle.
  • Registering listeners repeatedly on every view recreation.
  • Mixing ViewPager and ViewPager2 APIs in the same class.
  • Assuming callback order is identical across legacy and new implementations.
  • Leaving migration incomplete while dependencies already favor ViewPager2.

Summary

  • setOnPageChangeListener is deprecated in favor of add and remove listener APIs.
  • Use addOnPageChangeListener for legacy ViewPager migration.
  • Prefer ViewPager2 with register and unregister callback methods for modern apps.
  • Clean up listeners in lifecycle methods to avoid leaks and duplicate events.
  • Validate behavior with swipe and tab interaction tests after migration.

Course illustration
Course illustration

All Rights Reserved.