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?

Alex Lockwood
  • 83,063
  • 39
  • 206
  • 250

2 Answers2

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();
George Mount
  • 20,708
  • 2
  • 73
  • 61
  • Nice, but how do we postpone the setup of fragment1 after we are done in fragment2 and FragmentManager.popBackStack() is called? – mennovogel Apr 23 '15 at 07:26
  • 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. – George Mount Apr 23 '15 at 14:21
  • @GeorgeMount I'm experiencing problems with my fragment transitions (as per my [SO question](http://stackoverflow.com/questions/31283413/fragment-reentertransition-not-working-need-help-clarifying-the-various-fragmen)). 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? – Sound Conception Jul 08 '15 at 12:36
  • I hope this helps: https://halfthought.wordpress.com/2015/06/04/postponing-fragment-transitions/ – George Mount Jul 08 '15 at 19:21
  • @GeorgeMount. Thank you! The explanation and sample project are excellent! – Sound Conception Jul 09 '15 at 03:17
  • You said later when the fragment is ready, how do you know when thats happens? – user3497504 Sep 14 '15 at 18:23
  • 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. – George Mount Sep 14 '15 at 23:23
  • Hallelujah! Brilliant! – Miloš Černilovský Jun 01 '16 at 12:12
  • 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? – Wecherowski Aug 12 '19 at 18:39
  • Yes. This has changed. Fragment Transitions now exist. – George Mount Aug 12 '19 at 23:18
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.

Brown Smith
  • 754
  • 6
  • 6