I replaced ViewPager with ViewPager2, but I have problem with it. ViewPager has fixed 3 pages. And the second page larger than other. When page 1 or 3 is visible, a small part of page 2 is also visible, and when page 2 is visible, other pages are not visible. To do this I used method of adapter
override fun getPageWidth(position: Int): Float {
return if (position != MAIN_PAGE) WIDTH_SMALL_PERCENT
else super.getPageWidth(position)
}
But adapter of ViewPager2 don't has this method and I have no idea how do it.
Now it is impossible without hacks. I create feature request https://issuetracker.google.com/issues/150232913.
And in anticipation of features I create extension method to set custom layout manager
package androidx.viewpager2.widget
import androidx.recyclerview.widget.RecyclerView
import java.lang.reflect.Field
fun ViewPager2.setLayoutManager(layoutManager: RecyclerView.LayoutManager) {
mRecyclerView.layoutManager = layoutManager
mRecyclerView.clearOnChildAttachStateChangeListeners() // to ability set exact view size
setValueToField("mLayoutManager", layoutManager)
mScrollEventAdapter.setValueToField("mLayoutManager", layoutManager) // to correct work ViewPager2.OnPageChangeCallback
}
private fun Any.setValueToField(field: String, value: Any) {
val f1: Field = this.javaClass.getDeclaredField(field)
f1.isAccessible = true
f1.set(this, value)
f1.isAccessible = false
}
and create custom LayoutManager
class WidePageLayoutManager(
private val viewPager: ViewPager2,
private val viewSmallPercentage: Float,
private val smallViewPosition: IntArray
) : LinearLayoutManager(viewPager.context, HORIZONTAL, false) {
// copied from ViewPager2.LinearLayoutManagerImp
override fun calculateExtraLayoutSpace(state: RecyclerView.State, extraLayoutSpace: IntArray) {
val pageLimit: Int = viewPager.offscreenPageLimit
val offscreenSpace: Int = viewPager.pageSize * pageLimit
extraLayoutSpace[0] = offscreenSpace
extraLayoutSpace[1] = offscreenSpace
}
// copied from ViewPager2.LinearLayoutManagerImp
override fun requestChildRectangleOnScreen(
parent: RecyclerView,
child: View,
rect: Rect,
immediate: Boolean,
focusedChildVisible: Boolean
): Boolean {
return false // users should use setCurrentItem instead
}
// this need to show MainPage bounds on left/right side menu
override fun checkLayoutParams(lp: RecyclerView.LayoutParams?): Boolean {
if (lp != null && lp.viewAdapterPosition in smallViewPosition) {
lp.width = (width * viewSmallPercentage).toInt()
}
return super.checkLayoutParams(lp)
}
override fun canScrollHorizontally(): Boolean {
return super.canScrollHorizontally() && viewPager.isEnabled
}
}