Two pieces of fragments are displayed on orientation change to landscape with ViewPager2

Viewed 567

I am using ViewPager2 with WebView inside, on portrait mode it showing me single page, but when I switch to landscape mode it showing half of the current page and half of the previous page.

I have android:configChanges="orientation|screenSize" in the manifest to avoid destroying and recreating the viewpager.

Adapter

class ViewPageAdapter(
    private val tabs: ArrayList<Tab>, childFragmentManager: FragmentManager, lifecycle: Lifecycle
): FragmentStateAdapter(childFragmentManager, lifecycle) {
    override fun getItemCount(): Int = tabs.size

    override fun createFragment(position: Int): Fragment {
        return tabs[position].fragment
    }

    override fun containsItem(itemId: Long): Boolean {
        return tabs.map { it.tabId }.contains(itemId)
    }

    override fun getItemId(position: Int): Long {
        return tabs[position].tabId
    }

    fun removeItem(index: Int) {
        tabs.removeAt(index)
        notifyItemRemoved(index)
        notifyItemRangeChanged(index, tabs.size)
        notifyDataSetChanged()
    }
}

Setting up viewpager

adapter = ViewPageAdapter(browser.tabs, childFragmentManager, lifecycle)
binding.viewPager.adapter = adapter
binding.viewPager.offscreenPageLimit = 100
binding.viewPager.isUserInputEnabled = false

Portrait Mode Landscape Mode

1 Answers

It seems to be a bug in ViewPager2. https://issuetracker.google.com/issues/175796502?pli=1

I used the following workaround to fix the issue temporarily. The problem occures when I have a previous page, so what I did was switching to previous page and switch back to the current page without the smooth scrolling, I hope they will fix the bug as soon as possible.

override fun onConfigurationChanged(newConfig: Configuration) {
    super.onConfigurationChanged(newConfig)

    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE || newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
        val c = currentPageIndex
        binding.viewPager.setCurrentItem(if (currentPageIndex-1 > 0) currentPageIndex-1 else 0, false)
        binding.viewPager.setCurrentItem(c, false)
    }
}
Related