Reputation: 85
I am looking to migrate from ViewPager
to ViewPager2
. My existing ViewPager
contains ListFragment
s that support bulk editing via an ActionMode
. I need to cancel the current bulk editing operation when the user swipes from one page to another, so that the context header from one page isn't shown when viewing a different page.
With ViewPager
, I can override setPrimaryItem
in the ListFragment
's FragmentPagerAdapter
to know when one page replaces another. Crucially, this function takes as a parameter the actual child fragment that's becoming visible, which I can store in the adapter and later use to cancel bulk editing when it is replaced by another fragment.
How do I do the same thing with ViewPager2
, namely, know when a fragment is no longer visible? I have tried overriding Fragment.onPause
, but that's not what I want---it gets called whenever the phone screen turns off or the orientation changes, and I don't want to cancel bulk editing in these circumstances. I also have a callback registered via ViewPager2.registerOnPageChangeCallback
, but this gives me only the index of the new fragment, not the fragment itself or anything about the old fragment.
Upvotes: 4
Views: 1080
Reputation: 1550
I think the best solution is to register a FragmentTransactionCallback
. Downside - this was only added in the latest 1.1.0 alpha release of the ViewPager2 library.
There's a method on that class (FragmentTransactionCallback::onFragmentMaxLifecyclePreUpdated
) which is called whenever the ViewPager2
changes a Fragment's maximum Lifecycle state.
val basicAdapter: FragmentStateAdapter = // ....
basicAdapter.registerFragmentTransactionCallback(object : FragmentTransactionCallback() {
override fun onFragmentMaxLifecyclePreUpdated(fragment: Fragment, max: Lifecycle.State): OnPostEventListener {
// Check whether a Fragment is going to move from 'resumed' to 'started'
//
// Note that this check won't catch some types of smooth scroll:
// I'm not certain why, but I think it has to do with fragments
// already being paused before the method is called.
//
if (max == Lifecycle.State.STARTED && fragment.isResumed) {
// This fragment WAS the 'current item' but it's offscreen now.
return OnPostEventListener { TODO("Cancel Bulk Editing") }
}
return super.onFragmentMaxLifecyclePreUpdated(fragment, max)
}
})
Upvotes: 3