Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determining when fragment no longer visible in ViewPager2

I am looking to migrate from ViewPager to ViewPager2. My existing ViewPager contains ListFragments 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.

like image 506
Andrew Kirmse Avatar asked Oct 29 '25 13:10

Andrew Kirmse


1 Answers

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)
    }
})
like image 106
Cliabhach Avatar answered Oct 31 '25 04:10

Cliabhach



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!