NestedScrolling inside a Viewpager inside a BottomSheetDialog

I had some troubles with these previous responses. In fact, in my case the @NonNull Object object in setPrimaryItem method return a fragment and cannot be cast to a NestedScrollView.

Here what I have in my XML :

  • One BottomSheet containing a ViewPager.
  • The ViewPager with two pages containing one Fragment each.
  • Each Fragment Containing one NestedScrollView at the root view.

Here is my ViewPagerAdapter (Kotlin)

class MyViewPagerAdapter(val id: String) :
    FragmentStatePagerAdapter(supportFragmentManager) {

    val titles = arrayOf(getString(R.string.title1),
        getString(R.string.title2))

    override fun getItem(position: Int) = when (position) {
        0 -> MyFragment1.newInstance(id)
        1 -> MyFragment2.newInstance(id)
        else -> Fragment()
    }

    override fun getCount() = 2

    override fun getPageTitle(position: Int): CharSequence? {
        return titles[position]
    }

    override fun setPrimaryItem(container: ViewGroup, position: Int, `object`: Any) {
        super.setPrimaryItem(container, position, `object`)

        val currentFragment = `object` as Fragment

        if (currentFragment.view != null) { //The first time the view isn't created yet
            for (i in 0 until count) {
                (container.getChildAt(i) as NestedScrollView).isNestedScrollingEnabled = false
            }

            val currentNestedScrollView: NestedScrollView = currentFragment.view as NestedScrollView
            currentNestedScrollView.isNestedScrollingEnabled = true

            container.requestLayout()
        }
    }
}

After digging into the source code, I found that the problem lies on a faulty algorithm used in finding the NestedScrollingChild of the bottomsheet (folks at Google did not take into account the possiblity of a ViewPager inside the bottomsheet).

See the method here: findScrollingChild()

What this method does is it will return the first NestedScrollingChild it encounters on a given view (the bottomsheet in this case), which in the case of a viewpager with 3 pages, the one preceding the current page. Also, this method is triggered during the layout phase of the children of the CoordinatorLayout wrapper of the bottomsheet.

With this in mind, one can devise many solutions including subclassing the behavior itself.

Also, one can limit the NestedScrollingChild inside the viewpager by adding and removing one instance of such child (remove from the old page, then add in the current page), which is what I did. You can do this inside setPrimaryItem of the adapter or on a OnPageChangeListener. Just be sure to call requestLayout on the coordinator layout of the bottomsheet. (This solution depends on the kind of layout/structure of the pager adapter so I won't post my exact solution).