How to postpone a Fragment's enter transition in Android Lollipop?
T

2

17

In Android Lollipop, the Activity#postponeEnterTransition() and Activity#startPostponedEnterTransition() methods give the Activity the ability to delay starting the entering and exiting shared element transitions until all data is loaded. These work great for Activity transitions.

Is there a way to achieve the same effect when using Fragment transitions?

Tame answered 17/11, 2014 at 16:32 Comment(0)
C
13

There's no direct equivalent in Fragment Transitions because Fragments use FragmentTransaction and we can't really postpone something that is supposed to happen in a transaction.

To get the equivalent, you can add a Fragment and hide it in a transaction, then when the Fragment is ready, remove the old Fragment and show the new Fragment in a transaction.

getFragmentManager().beginTransaction()
    .add(R.id.container, fragment2)
    .hide(fragment2)
    .commit();

Later, when fragment2 is ready:

getFragmentManager().beginTransaction()
    .addSharedElement(sharedElement, "name")
    .remove(fragment1)
    .show(fragment2)
    .commit();
Cristinacristine answered 18/11, 2014 at 0:5 Comment(10)
Nice, but how do we postpone the setup of fragment1 after we are done in fragment2 and FragmentManager.popBackStack() is called?Apotheosis
If you don't remove fragment1, but hide it instead, it will make your life easier. If not, an extra step is necessary, but it works in the same way. a) add 2, hide 2 b) show 2, hide, add to back stack 1 c) show 1, remove1, add to back stack. Then you detect that you have arrived at (c) the second time, you wait for 1 to be ready and then pop the back stack programmatically.Cristinacristine
@GeorgeMount I'm experiencing problems with my fragment transitions (as per my SO question). Starting to think it's because my fragments aren't ready when the animations begin. In your above comment I understand steps a) and b), but "c) show 1, remove1, add to back stack. Then you detect that you have arrived at (c) the second time, you wait for 1 to be ready and then pop the back stack programmatically." is confusing me a bit. Can you expand on that a little?Rolland
I hope this helps: halfthought.wordpress.com/2015/06/04/…Cristinacristine
@GeorgeMount. Thank you! The explanation and sample project are excellent!Rolland
You said later when the fragment is ready, how do you know when thats happens?Journalist
This depends on what is causing the delay. In my example, I wait for the RecyclerView to do a layout by adding an onPreDrawListener. In your app, you may need to wait for a Bitmap to load or database activity or any number of things.Cristinacristine
Hallelujah! Brilliant!Fusspot
But this has changed since 2015, right? It's possible ow but you have to set Reordering to true .. Or is that a different story?Aiaia
Yes. This has changed. Fragment Transitions now exist.Cristinacristine
H
3

You can postpone Fragment's enter transition by doing the following:

  • Allow FragmentTransaction to re-order & optimize the transaction

    requireActivity().supportFragmentManager
      .beginTransaction()
      .replace(R.id.container, fragmentB)
      .addSharedElement(view, "transitionName")
      .setReorderingAllowed(true) // Set to true
      .commit()
    
  • Tell fragmentB to delay the transition after view creation

    class TransitionToFragment : Fragment(R.layout.fragment_b) {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
      super.onViewCreated(view, savedInstanceState)
      postponeEnterTransition() // Don't start enter transitions yet!
    
      ... // Setup your views
    
      (view.parent as? View)?.doOnPreDraw { startPostponedEnterTransition() } // Ok, start transitions
    }
    }
    

    view.parent.doOnPreDraw { ... } is used to ensure the fragment's views are measured and laid out for the transition. See Chris Banes's blog for more details.

Hallel answered 14/7, 2020 at 17:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.