I've been trying all the suggestions, solutions, libraries, etc but they're not pure circular and most of the time don't have support for only 3 pages.
So I implemented a circular ViewPager
example using the new ViewPager2
, the new ViewPager
uses a RecyclerView
and ViewHolder
s to handle the views recycling and works as expected!
TLDR: GITHUB
In this example, will be building a single activity app with ViewPager2
and a FragmentPagerAdapter
supporting circular navigation between 3 pages or more.
I'm using an alpha version of the library androidx.viewpager2:viewpager2
, but the version 1.0.0-alpha06
is the last one planned before google freezing the API and moving to beta.
1. Add the ViewPager2
library to the dependencies in your build.gradle
dependencies {
implementation 'androidx.viewpager2:viewpager2:1.0.0-alpha06'
}
2. Add the ViewPager2
view to your project:
<androidx.viewpager2.widget.ViewPager2 xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/vwpHome"
android:layout_width="match_parent"
android:layout_height="match_parent" />
3. Create the FragmentStateAdapter
adapter:
getItemCount()
needs to returns a huuuuge number. (2147483647)
getCenterPage()
returns the central page based on the huuuuge number.
This method is used to get the position of the initial page to set in the ViewPager2
, in this case the user needs to swipe ˜1073741823 time to reach the end of the ViewPager2
.
class CircularPagerAdapter(fragmentManager: FragmentManager, lifecycle: Lifecycle) : FragmentStateAdapter(fragmentManager, lifecycle) {
override fun getItemCount() = Integer.MAX_VALUE
/**
* Create the fragment based on the position
*/
override fun createFragment(position: Int) = HomePagerScreens.values()[position % HomePagerScreens.values().size].fragment.java.newInstance()
/**
* Returns the same id for the same Fragment.
*/
override fun getItemId(position: Int): Long = (position % HomePagerScreens.values().size).toLong()
fun getCenterPage(position: Int = 0) = Integer.MAX_VALUE / 2 + position
}
HomeScreens is a ENUM with the page info.
enum class HomePagerScreens(@StringRes val title: Int,
val fragment: KClass<out Fragment>) {
HOME_1(R.string.home_1, FragmentHome::class),
HOME_2(R.string.home_2, FragmentHome::class),
HOME_3(R.string.home_3, FragmentHome::class)
}
4. Set the adapter to the ViewPager
val circularAdapter = CircularPagerAdapter(supportFragmentManager, lifecycle)
vwpHome.apply {
adapter = circularAdapter
setCurrentItem(circularAdapter.getCenterPage(), false)
}
ViewPager
, but you might try modifyingFragmentStatePagerAdapter.instantiateItem
to use some modulus math to load the proper Fragment. You'll need to overridegetCount
to return a sufficiently large number. – DiscardViewPager.mCurPos
is private... – Punjabi