Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Transitions without Activities or Fragments

7b1e567c19126de48554fe8e5e767395?s=47 Chris Horner
November 05, 2017

Transitions without Activities or Fragments

Android's Transition framework is extremely powerful, but almost all examples involve the use of Activities and Fragments. In a world where many developers are now foregoing Fragments, this talk aims to provide some solid examples and strategies on how to use Transitions without them.

7b1e567c19126de48554fe8e5e767395?s=128

Chris Horner

November 05, 2017
Tweet

Transcript

  1. Transitions without Activities or Fragments @chris_h_codes

  2. Transitions are slick

  3. Transitions are slick

  4. Transitions are slick

  5. Not like this

  6. Teleportation sucks

  7. Teleportation sucks

  8. Avoiding an ‘event boundary’

  9. Avoiding an ‘event boundary’ ?

  10. Walking through doorways causes forgetting: Situation models and experienced space

    ? * https://doi.org/10.3758/BF03193261
  11. None
  12. None
  13. My Animator code works! Animator animator = ObjectAnimator.ofFloat(0f, 10f); button.animate()

    .alpha(0) .translationY(200);
  14. Transitions are powerful • Easier to compose than traditional Animator

    code • Allow for shared elements
  15. Learning about Transitions Developers Generate Scenes from Layouts Apply a

    Transition without Scenes
  16. Transitions - Google IO YouTube Now you call Activity.makeSceneTransitionAnimation() Learning

    about Transitions
  17. YouTube Square - Avoiding Fragments Use #fragnums, lol Learning about

    Transitions
  18. This is not a Fragment bashing talk • Conductor •

    Flow • Pancakes • PancakesOnPlates • Scoop • Cicerone • BackStack • Magellan • Simple Stack • Triad • Okuki • Navi
  19. This talk is about two scenarios ViewGroup

  20. This talk is about two scenarios ViewGroup View1

  21. This talk is about two scenarios View1 View2

  22. This talk is about two scenarios View2 View1

  23. This talk is about two scenarios TransitionManager.beginDelayedTransition()

  24. This talk is about two scenarios TransitionManager.beginDelayedTransition()

  25. Simple layout changes <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="16dp" >

  26. <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="16dp" > blueView.setVisibility(View.VISIBLE);

  27. <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent"
 android:animateLayoutChanges="true" android:orientation="vertical" android:padding="16dp" > The forgotten Honeycomb

    API
  28. Oreo changes things <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent"
 android:animateLayoutChanges="true" android:orientation="vertical" android:padding="16dp" >

  29. LayoutTransition layoutTransition = container .getLayoutTransition(); layoutTransition .enableTransitionType(LayoutTransition.CHANGING); Jelly Bean tricks

  30. <LinearLayout android:layout_width="match_parent" android:layout_height=“match_parent" android:orientation=“vertical” android:padding="16dp" > Using TransitionManager

  31. <LinearLayout android:layout_width="match_parent" android:layout_height=“match_parent" android:orientation=“vertical” android:padding="16dp" > TransitionManager.beginDelayedTransition(container); View view =

    findViewById(R.id.blueView); view.setVisibility(View.VISIBLE);
  32. Complex example

  33. None
  34. None
  35. None
  36. None
  37. <LinearLayout> <TextView android:text=“Alarm”/> <TextView android:text=“Triggering…”/> <Space android:layout_weight=“1”/> <Button android:text=“Call 000”/>

    <Button android:text=“Help” android:layout_marginBottom=“280dp”/> </LinearLayout> Make a simple version
  38. <LinearLayout> <TextView android:text=“Alarm”/> <TextView android:text=“Triggering…”/> <Space android:layout_weight=“1”/> <Button android:text=“Call 000”/>

    <Button android:text=“Help” android:layout_marginBottom=“280dp”/> </LinearLayout>
  39. <FrameLayout> <!-- Map and text… -->
 <LinearLayout> <TextView android:text=“Alarm”/> <TextView

    android:text=“Triggering…”/> <Space android:layout_weight=“1”/> <Button android:text=“Call 000”/> <Button android:text=“Help” android:layout_marginBottom=“280dp”/> </LinearLayout> </FrameLayout>
  40. <FrameLayout> <!-- Map and text… -->
 <LinearLayout android:background=“#F2F2F2”> <TextView android:text=“Alarm”/>

    <TextView android:text=“Triggering…”/> <Space android:layout_weight=“1”/> <Button android:text=“Call 000”/> <Button android:text=“Help” android:layout_marginBottom=“280dp”/> </LinearLayout> </FrameLayout>
  41. <LinearLayout android:layout_width=“match_parent” android:layout_height=“match_parent” >

  42. helpButton.setOnClickListener(v -> { TransitionManager.beginDelayedTransition(linearContainer); LayoutParams containerParams = linearContainer.getLayoutParams(); containerParams.height =

    LayoutParams.WRAP_CONTENT; });
  43. helpButton.setOnClickListener(v -> { TransitionManager.beginDelayedTransition(linearContainer); LayoutParams containerParams = linearContainer.getLayoutParams(); containerParams.height =

    LayoutParams.WRAP_CONTENT; title.setVisibility(View.GONE); instructions.setVisibility(View.GONE); helpButton.setVisibility(View.GONE); okButton.setVisibility(View.VISIBLE); });
  44. helpButton.setOnClickListener(v -> { TransitionManager.beginDelayedTransition(linearContainer); LayoutParams containerParams = linearContainer.getLayoutParams(); containerParams.height =

    LayoutParams.WRAP_CONTENT; title.setVisibility(View.GONE); instructions.setVisibility(View.GONE); helpButton.setVisibility(View.GONE); okButton.setVisibility(View.VISIBLE); });
  45. TransitionManager .beginDelayedTransition(linearContainer);

  46. TransitionManager .beginDelayedTransition(linearContainer, transition); Customise the Transition

  47. Transition transition = new TransitionSet() .addTransition(new Fade() .addTarget(title) .addTarget(instructions) .addTarget(helpButton)

    .addTarget(okButton)) .addTransition(new ChangeBounds() .addTarget(linearContainer)); TransitionManager .beginDelayedTransition(linearContainer, transition); Customise the Transition
  48. Transition transition = new TransitionSet() .addTransition(new Fade() .addTarget(title) .addTarget(instructions) .addTarget(helpButton)

    .addTarget(okButton)) .addTransition(new ChangeBounds() .addTarget(linearContainer)); TransitionManager .beginDelayedTransition(linearContainer, transition);
  49. Transition transition = new TransitionSet() .addTransition(new Fade() .addTarget(title) .addTarget(instructions) .addTarget(helpButton)

    .addTarget(okButton)) .addTransition(new ChangeBounds() .addTarget(linearContainer)); TransitionManager .beginDelayedTransition(linearContainer, transition);
  50. Transition transition = new TransitionSet() .addTransition(new Fade() .addTarget(title) .addTarget(instructions) .addTarget(helpButton)

    .addTarget(okButton)) .addTransition(new ChangeBounds() .addTarget(linearContainer)); TransitionManager .beginDelayedTransition(linearContainer, transition);
  51. Transition transition = new TransitionSet() .addTransition(new Fade() .addTarget(title) .addTarget(instructions) .addTarget(helpButton)

    .addTarget(okButton)) .addTransition(new ChangeBounds() .addTarget(linearContainer) .addTarget(callButton)); TransitionManager .beginDelayedTransition(linearContainer, transition);
  52. Transition transition = new TransitionSet() .addTransition(new Fade() .addTarget(title) .addTarget(instructions) .addTarget(helpButton)

    .addTarget(okButton)) .addTransition(new ChangeBounds() .addTarget(linearContainer) .addTarget(callButton) .addTarget(okButton) .addTarget(helpButton)); TransitionManager .beginDelayedTransition(linearContainer, transition);
  53. <FrameLayout> <!-- Map and text… —>
 <LinearLayout android:background=“#F2F2F2”> <TextView android:text=“Alarm”/>

    <TextView android:text=“Triggering…”/> <Space android:layout_weight=“1”/> <Button android:text=“Call 000”/> <Button android:text=“Help” android:layout_marginBottom=“280dp”/> </LinearLayout> </FrameLayout>
  54. <FrameLayout> <!-- Map and text… —> <View android:background=“#F2F2F2”/>
 <LinearLayout> <TextView

    android:text=“Alarm”/> <TextView android:text=“Triggering…”/> <Space android:layout_weight=“1”/> <Button android:text=“Call 000”/> <Button android:text=“Help” android:layout_marginBottom=“280dp”/> </LinearLayout> </FrameLayout>
  55. <!-- Map and text… —> <View android:background=“#F2F2F2”/>
 <LinearLayout> <TextView android:text=“Alarm”/>

    <TextView android:text=“Triggering…”/> </LinearLayout> <LinearLayout> <Button android:text=“Call 000”/> <Button android:text=“Help” android:layout_marginBottom=“280dp”/> </LinearLayout>
  56. <!-- Map and text… —> <View android:background=“#F2F2F2” android:layout_height=“???”/>
 <LinearLayout> <TextView

    android:text=“Alarm”/> <TextView android:text=“Triggering…”/> </LinearLayout> <LinearLayout android:layout_height=“wrap_content”> <Button android:text=“Call 000”/> <Button android:text=“Help” android:layout_marginBottom=“280dp”/> </LinearLayout>
  57. <ConstraintLayout> <!-- Map and text… —> <View android:background=“#F2F2F2”/>
 <TextView android:text=“Alarm”/>

    <TextView android:text=“Triggering…”/> <Button android:text=“Call 000”/> <Button android:text=“Help”/> </ConstraintLayout>
  58. <ConstraintLayout> <!-- Map and text… —> <View android:background=“#F2F2F2”/>
 <TextView android:text=“Alarm”/>

    <TextView android:text=“Triggering…”/> <Guideline app:layout_constraintGuide_percent=“0.6”/> <Button android:text=“Call 000”/> <Button android:text=“Help”/> </ConstraintLayout>
  59. ConstraintLayout container = findViewById(R.id.container); ConstraintSet idleSet = new ConstraintSet(); ConstraintSet

    triggeredSet = new ConstraintSet(); idleSet.clone(container); triggeredSet.clone(container); Take advantage of ConstraintSet
  60. ConstraintLayout container = findViewById(R.id.container); ConstraintSet idleSet = new ConstraintSet(); ConstraintSet

    triggeredSet = new ConstraintSet(); idleSet.clone(container); triggeredSet.clone(container); triggeredSet.setVisibility(R.id.title, View.GONE); triggeredSet.setVisibility(R.id.instructions, View.GONE); triggeredSet.setVisibility(R.id.helpButton, View.GONE); triggeredSet.setVisibility(R.id.okButton, View.VISIBLE); triggeredSet.connect(R.id.whiteBackground, ConstraintSet.TOP, R.id.guideline, ConstraintSet.TOP); Take advantage of ConstraintSet
  61. ConstraintLayout container = findViewById(R.id.container); ConstraintSet idleSet = new ConstraintSet(); ConstraintSet

    triggeredSet = new ConstraintSet(); idleSet.clone(container); triggeredSet.clone(container); triggeredSet.setVisibility(R.id.title, View.GONE); triggeredSet.setVisibility(R.id.instructions, View.GONE); triggeredSet.setVisibility(R.id.helpButton, View.GONE); triggeredSet.setVisibility(R.id.okButton, View.VISIBLE); triggeredSet.connect(R.id.whiteBackground, ConstraintSet.TOP, R.id.guideline, ConstraintSet.TOP); helpButton.setOnClickListener(v -> { TransitionManager.beginDelayedTransition(container); triggeredSet.applyTo(container); }); Take advantage of ConstraintSet
  62. helpButton.setOnClickListener(v -> { TransitionManager .beginDelayedTransition(container, new AutoTransition()); triggeredSet.applyTo(container); }); Take

    advantage of ConstraintSet
  63. public class AutoTransition extends TransitionSet { private void init() {

    setOrdering(ORDERING_SEQUENTIAL); addTransition(new Fade(Fade.OUT)); addTransition(new ChangeBounds()); addTransition(new Fade(Fade.IN)); } }
  64. Transition transition = new TransitionSet() .addTransition(new Fade()) .addTransition(new ChangeBounds()); TransitionManager

    .beginDelayedTransition(container, transition);
  65. Transition transition = new TransitionSet() .addTransition(new Fade()) .addTransition(new ChangeBounds()); TransitionManager

    .beginDelayedTransition(container, transition);
  66. Transition transition = new TransitionSet() .addTransition(new Fade() .addTarget(title) .addTarget(instructions) .setDuration(100))

    .addTransition(new Fade() .addTarget(helpButton) .addTarget(okButton) .setDuration(400)) .addTransition(new ChangeBounds() .setDuration(400) .setInterpolator(new FastOutSlowInInterpolator()); TransitionManager .beginDelayedTransition(container, transition);
  67. Switching screens

  68. None
  69. None
  70. None
  71. <FrameLayout> <TextView android:text=“Home screen”/> <BottomNavigationView/> <FloatingActionButton/> </FrameLayout> Make a simple

    version
  72. ViewGroup

  73. ViewGroup

  74. ViewGroup

  75. ViewGroup

  76. ViewGroup TransitionManager.beginDelayedTransition(viewGroup); viewGroup.remove(homeView); viewGroup.add(alarmView);

  77. ViewGroup What if we use Fade? TransitionManager .beginDelayedTransition(viewGroup, new Fade());

    viewGroup.remove(homeView); viewGroup.add(alarmView);
  78. ViewGroup TransitionManager .beginDelayedTransition(viewGroup, new Slide()); viewGroup.remove(homeView); viewGroup.add(alarmView); What if we

    use Slide?
  79. ViewGroup Transition transition = new TransitionSet() .addTransition(new Slide(Gravity.START) .addTarget(homeView) .setInterpolator(new

    FastOutSlowInInterpolator()) .addTransition(new Slide(Gravity.END) .addTarget(alarmView) .setInterpolator(new FastOutSlowInInterpolator()); TransitionManager .beginDelayedTransition(viewGroup, transition); viewGroup.remove(homeView); viewGroup.add(alarmView); A nicer Slide
  80. ViewGroup Transition transition = new TransitionSet() .addTransition(new Slide(Gravity.START) .addTarget(alarmView) .setInterpolator(new

    FastOutSlowInInterpolator()); TransitionManager .beginDelayedTransition(viewGroup, transition); viewGroup.remove(homeView); viewGroup.add(alarmView);
  81. ViewGroup Sliding over Transition transition = new TransitionSet() .addTransition(new Slide(Gravity.BOTTOM)

    .addTarget(alarmView) .setInterpolator(new LinearOutSlowInInterpolator()); TransitionManager .beginDelayedTransition(viewGroup, transition); viewGroup.remove(homeView); viewGroup.add(alarmView);
  82. ViewGroup Transition transition = new TransitionSet() .addTransition(new Fade() .addTarget(homeView) .setStartDelay(300)

    .setDuration(0)) .addTransition(new Slide(Gravity.BOTTOM) .addTarget(alarmView) .setInterpolator(new LinearOutSlowInInterpolator()); TransitionManager .beginDelayedTransition(viewGroup, transition); viewGroup.remove(homeView); viewGroup.add(alarmView); Sliding over
  83. ViewGroup Transition transition = new TransitionSet() .addTransition(new Fade() .addTarget(homeView) .setStartDelay(300)

    .setDuration(0)) .addTransition(new Slide(Gravity.BOTTOM) .addTarget(alarmView) .setInterpolator(new LinearOutSlowInInterpolator()); TransitionManager .beginDelayedTransition(viewGroup, transition); viewGroup.remove(homeView); viewGroup.add(alarmView); Sliding over
  84. ViewGroup

  85. ViewGroup

  86. ViewGroup

  87. ViewGroup

  88. Read your library of choice’s documentation carefully! ViewGroup

  89. ViewGroup Transition transition = new TransitionSet() .addTransition(new Slide(Gravity.BOTTOM) .addTarget(alarmView) .setInterpolator(new

    LinearOutSlowInInterpolator()); TransitionManager .beginDelayedTransition(viewGroup, transition); viewGroup.remove(homeView); viewGroup.add(alarmView);
  90. ViewGroup Transition transition = new TransitionSet() .addTransition(new Slide(Gravity.BOTTOM) .addTarget(alarmView) .setInterpolator(new

    LinearOutSlowInInterpolator()); TransitionManager .beginDelayedTransition(viewGroup, transition); viewGroup.remove(homeView); viewGroup.add(alarmView);
  91. ViewGroup Transition transition = new TransitionSet() .addTransition(new Slide(Gravity.BOTTOM) .addTarget(alarmView) .setInterpolator(new

    LinearOutSlowInInterpolator()); TransitionManager .beginDelayedTransition(viewGroup, transition); viewGroup.add(alarmView);
  92. ViewGroup Transition transition = new TransitionSet() .addTransition(new Slide(Gravity.BOTTOM) .addTarget(alarmView) .setInterpolator(new

    LinearOutSlowInInterpolator()) .addListener(new Transition.TransitionListener() { @Override onTransitionEnd(Transition transition) { container.removeView(homeView); } }); TransitionManager .beginDelayedTransition(viewGroup, transition); viewGroup.add(alarmView);
  93. ViewGroup Transition transition = new TransitionSet() .addTransition(new Slide(Gravity.BOTTOM) .addTarget(alarmView) .setInterpolator(new

    LinearOutSlowInInterpolator()) .addListener(new Transition.TransitionListener() { @Override onTransitionEnd(Transition transition) { container.removeView(homeView); } }); TransitionManager .beginDelayedTransition(viewGroup, transition); viewGroup.add(alarmView);
  94. ViewGroup Sharing elements

  95. ViewGroup Sharing elements Transition transition = new TransitionSet() .addTransition(new Slide(Gravity.BOTTOM)

    .addTarget(alarmView) .setInterpolator(new LinearOutSlowInInterpolator());
  96. ViewGroup Transition transition = new TransitionSet() .addTransition(new Slide(Gravity.BOTTOM) .addTarget(alarmView) .setInterpolator(new

    LinearOutSlowInInterpolator()) .addTransition(new ChangeBounds() .addTarget(homeView.fab) .addTarget(alarmView.fab)); Sharing elements
  97. ViewGroup Transition transition = new TransitionSet() .addTransition(new Slide(Gravity.BOTTOM) .addTarget(alarmView) .setInterpolator(new

    LinearOutSlowInInterpolator()) .addTransition(new ChangeBounds() .addTarget(homeView.fab) .addTarget(alarmView.fab)); TransitionManager .beginDelayedTransition(viewGroup, transition); viewGroup.add(alarmView); Sharing elements
  98. ViewGroup <ConstraintLayout android:layout_width=“match_parent” android:layout_height=“match_parent” > Breaking up views

  99. ViewGroup <ConstraintLayout android:layout_width=“match_parent” android:layout_height=“match_parent” android:transitionGroup=“false” > Breaking up views

  100. ViewGroup <ConstraintLayout android:layout_width=“match_parent” android:layout_height=“match_parent” > Breaking up views

  101. ViewGroup <ConstraintLayout android:id=“@+id/contentContainer” android:layout_width=“match_parent” android:layout_height=“match_parent” > Breaking up views

  102. ViewGroup <FrameLayout android:layout_width=“match_parent” android:layout_height=“match_parent” > <ConstraintLayout android:id=“@+id/contentContainer” android:layout_width=“match_parent” android:layout_height=“match_parent” >

    <FloatingActionButton android:id=“@+id/fab” android:layout_width=“wrap_content” android:layout_height=“wrap_content” > </FrameLayout> Breaking up views
  103. ViewGroup Transition transition = new TransitionSet() .addTransition(new Slide(Gravity.BOTTOM) .addTarget(alarmView) .setInterpolator(new

    LinearOutSlowInInterpolator()) .addTransition(new ChangeBounds() .addTarget(homeView.fab) .addTarget(alarmView.fab)); TransitionManager .beginDelayedTransition(viewGroup, transition); viewGroup.add(alarmView);
  104. ViewGroup Transition transition = new TransitionSet() .addTransition(new Slide(Gravity.BOTTOM) .addTarget(alarmView.contentContainer) .setInterpolator(new

    LinearOutSlowInInterpolator()) .addTransition(new ChangeBounds() .addTarget(homeView.fab) .addTarget(alarmView.fab)); TransitionManager .beginDelayedTransition(viewGroup, transition); viewGroup.add(alarmView);
  105. ViewGroup Transition transition = new TransitionSet() .addTransition(new Slide(Gravity.BOTTOM) .addTarget(alarmView.contentContainer) .setInterpolator(new

    LinearOutSlowInInterpolator()) .addTransition(new ChangeBounds() .addTarget(homeView.fab) .addTarget(alarmView.fab)); TransitionManager .beginDelayedTransition(viewGroup, transition); viewGroup.add(alarmView);
  106. ViewGroup Transition transition = new TransitionSet() .addTransition(new Slide(Gravity.BOTTOM) .addTarget(alarmView.contentContainer) .setInterpolator(new

    LinearOutSlowInInterpolator()) .addTransition(new ChangeBounds() .addTarget(homeView.fab) .addTarget(alarmView.fab)); TransitionManager .beginDelayedTransition(viewGroup, transition); viewGroup.add(alarmView);
  107. ViewGroup Transition transition = new TransitionSet() .addTransition(new Slide(Gravity.BOTTOM) .addTarget(alarmView.contentContainer) .setInterpolator(new

    LinearOutSlowInInterpolator()) .addTransition(new ChangeBounds() .addTarget(homeView.fab) .addTarget(alarmView.fab)); TransitionManager .beginDelayedTransition(viewGroup, transition); viewGroup.add(alarmView); homeView.removeView(homeView.fab);
  108. ViewGroup <!-- home.xml --> <FloatingActionButton android:id=“@+id/fab” android:layout_width=“wrap_content” android:layout_height=“wrap_content” > 


    <!-- alarm.xml --> <FloatingActionButton android:id=“@+id/fab” android:layout_width=“wrap_content” android:layout_height=“wrap_content” >
  109. ViewGroup <!-- home.xml --> <FloatingActionButton android:id=“@+id/fab” android:layout_width=“wrap_content” android:layout_height=“wrap_content” > 


    <!-- alarm.xml --> <FloatingActionButton android:id=“@+id/fab” android:layout_width=“wrap_content” android:layout_height=“wrap_content” >
  110. ViewGroup <!-- home.xml --> <FloatingActionButton android:id=“@+id/home_fab” android:transitionName=“fab” android:layout_width=“wrap_content” android:layout_height=“wrap_content” >

    
 <!-- alarm.xml --> <FloatingActionButton android:id=“@+id/alarm_fab” android:transitionName=“fab” android:layout_width=“wrap_content” android:layout_height=“wrap_content” >
  111. Same but different

  112. None
  113. None
  114. <LinearLayout android:orientation=“vertical”> <AppBarLayout…/> <CardView…/> <Space android:layout_weight=“1”/> <TextView/> <Space android:layout_weight=“1”/> </LinearLayout>

  115. <FrameLayout android:background=“#66000000”> <CardView…/> <ImageButton/> <EditText/> <View android:background=“@android:drawable/ divider_horizontal_bright”/> <RecyclerView…/> </CardView>

    </FrameLayout>
  116. <FrameLayout> <View android:background=“#66000000”/> <CardView…/> <ImageButton/> <EditText/> <View android:background=“@android:drawable/ divider_horizontal_bright”/> <RecyclerView…/>

    </CardView> </FrameLayout>
  117. <!-- home.xml -->
 
 <CardView android:transitionName=“card” />
 
 <!-- search.xml

    -->
 
 <CardView android:transitionName=“card” />
  118. Transition transition = new TransitionSet() .addTransition(new Fade() .addTarget(searchView.scrim)) .addTransition(new ChangeBounds()

    .addTarget(homeView.card) .addTarget(searchView.card)); <!-- home.xml -->
 
 <CardView android:transitionName=“card” />
 
 <!-- search.xml -->
 
 <CardView android:transitionName=“card” />
  119. Transition transition = new TransitionSet() .addTransition(new Fade() .addTarget(searchView.scrim)) .addTransition(new ChangeBounds()

    .addTarget(homeView.card) .addTarget(searchView.card)); TransitionManager .beginDelayedTransition(viewGroup, transition); container.addView(searchView); 
 <CardView android:transitionName=“card” />
 
 <!-- search.xml -->
 
 <CardView android:transitionName=“card” />
  120. Transition transition = new TransitionSet() .addTransition(new Fade() .addTarget(searchView.scrim)) .addTransition(new ChangeBounds()

    .addTarget(homeView.card) .addTarget(searchView.card)); TransitionManager .beginDelayedTransition(viewGroup, transition); container.addView(searchView);
  121. Transition transition = new TransitionSet() .addTransition(new Fade() .addTarget(searchView.scrim)) .addTransition(new ChangeBounds()

    .addTarget(homeView.card) .addTarget(searchView.card)); TransitionManager .beginDelayedTransition(viewGroup, transition); container.addView(searchView); homeView.removeView(homeView.card);
  122. <LinearLayout android:orientation=“vertical”> <AppBarLayout…/> <CardView…/> <Space android:layout_weight=“1”/> <TextView/> <Space android:layout_weight=“1”/> </LinearLayout>

  123. <LinearLayout android:orientation=“vertical”> <AppBarLayout…/> <FrameLayout android:id=“@+id/cardSlot”> <CardView…/> </FrameLayout/> <Space android:layout_weight=“1”/> <TextView/>

    <Space android:layout_weight=“1”/> </LinearLayout>
  124. Transition transition = new TransitionSet() .addTransition(new Fade() .addTarget(searchView.scrim)) .addTransition(new ChangeBounds()

    .addTarget(homeView.card) .addTarget(searchView.card)); TransitionManager .beginDelayedTransition(viewGroup, transition); homeView.removeView(homeView.card);
  125. Transition transition = new TransitionSet() .addTransition(new Fade() .addTarget(searchView.scrim)) .addTransition(new ChangeBounds()

    .addTarget(homeView.card) .addTarget(searchView.card)); TransitionManager .beginDelayedTransition(viewGroup, transition); homeView.removeView(homeView.card);
  126. Transition transition = new TransitionSet() .addTransition(new Fade() .addTarget(searchView.scrim)) .addTransition(new TransitionSet()

    .addTransition(new ChangeBounds()) .addTransition(new ChangeTransform()) .addTarget(homeView.card) .addTarget(searchView.card)); TransitionManager .beginDelayedTransition(viewGroup, transition); homeView.removeView(homeView.card);
  127. What about going back?

  128. Transition transition = new TransitionSet() .addTransition(new Fade() .addTarget(searchView.scrim)) .addTransition(new TransitionSet()

    .addTransition(new ChangeBounds()) .addTransition(new ChangeTransform()) .addTarget(homeView.card) .addTarget(searchView.card)); TransitionManager .beginDelayedTransition(viewGroup, transition); homeView.addView(homeView.card); container.removeView(searchView); What about going back?
  129. Transition transition = new TransitionSet() .addTransition(new Fade() .addTarget(searchView.scrim)) .addTransition(new TransitionSet()

    .addTransition(new ChangeBounds()) .addTransition(new ChangeTransform()) .addTarget(homeView.card) .addTarget(searchView.card)); TransitionManager .beginDelayedTransition(viewGroup, transition); homeView.addView(homeView.card); container.removeView(searchView);
  130. Transition transition = new TransitionSet() .addTransition(new Fade() .addTarget(searchView.scrim)) .addTransition(new TransitionSet()

    .addTransition(new ChangeBounds()) .addTransition(new ChangeTransform()) .addTarget(homeView.card) .addTarget(searchView.card)); TransitionManager .beginDelayedTransition(viewGroup, transition); homeView.addView(homeView.card); container.removeView(searchView);
  131. Transition transition = new TransitionSet() .addTransition(new Fade() .addTarget(searchView.scrim)) .addTransition(new TransitionSet()

    .addTransition(new ChangeBounds()) .addTransition(new ChangeTransform()) .addTarget(R.id.homeCard) .addTarget(searchView.card)); TransitionManager .beginDelayedTransition(viewGroup, transition); homeView.addView(homeView.card); container.removeView(searchView);
  132. Transitions aren’t perfect

  133. None
  134. Debugging tips • Know your layout hierarchy • ChangeBounds() is

    a good place to start investigating • Try starting with simplified versions of your screens
  135. Things to remember • Transitions are powerful; don’t ignore them

    • Choose your view-based navigation library carefully • Use them to enhance UX, not show off
  136. Transitions without Activities or Fragments chris_h_codes chris-horner chrishorner.codes