androidandroid-fragmentsandroid-viewpager2

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


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


Solution

  • 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)
        }
    }