Pro Yearly is on sale from $80 to $50! »

Make your app dance with MotionLayout

Make your app dance with MotionLayout

Intro to the brand new MotionLayout (ConstraintLayout 2.0). How and why to use it to animate your Android app and make it dance ~*~*~*

Happy people - dance. Happy apps - animate!
Happy devs - easily write delightful apps which make their users happy!

2 years ago, when ConstraintLayout was born, it added to the family performat expressive layouts. Since then, it grew and evolved, and became abundant with powerful animation opportunities!

ConstraintSet, Key Frames and the new shiney MotionLayout - this session will utilize them all to make your apps dance, and your users happy!

Presented at DroidconNYC 2018

3142db3adb711e247e371153b5777e04?s=128

Britt Barak

August 28, 2018
Tweet

Transcript

  1. Make your app dance With MotionLayout Gif: @evanmcohen @BrittBarak

  2. Why do we to dance? @BrittBarak

  3. When is comes to animations @BrittBarak

  4. Britt Barak DevRel @ Nexmo Google Developer Expert Women Techmakers

    Israel @brittBarak Britt Barak
  5. ConstraintLayout Gif from Android Developers Blog @BrittBarak

  6. Have you met MotionLayout? @BrittBarak

  7. Have you met MotionLayout? •Motion driven by user interaction •Extends

    ConstraintLayout •ConstraintLayout 2.0 (alpha 2) •Support from API-14 Gif: @Opintrius @BrittBarak
  8. How to make your app dance with MotionLayout? Gif: @Opintrius

    @BrittBarak
  9. How to make your CURRENT app dance with MotionLayout? Gif:

    @Opintrius @BrittBarak
  10. @BrittBarak

  11. Let’s start ! @BrittBarak

  12. None
  13. -1- Layout Define the players on the screen @BrittBarak

  14. <androidx.constraintlayout.motion.widget.MotionLayout android:id=“@+id/motionLayout" … > … </androidx.constraintlayout.motion.widget.MotionLayout> layout_call.xml @BrittBarak

  15. -2- Define Scenes Define the movers @BrittBarak

  16. -2- Define Scenes @BrittBarak

  17. -2- Define Scenes @BrittBarak

  18. -2- Define Scenes @BrittBarak

  19. -2- Start & End (layouts) layout/ keypad_down.xml layout/ keypad_up.xml @BrittBarak

  20. layout_call keypad_down keypad_up @BrittBarak

  21. layout_call keypad_down keypad_up constraintSet constraintSet @BrittBarak

  22. keypad_down keypad_up constraintSet constraintSet layout_call • Same view IDs •

    Rewrite constrains @BrittBarak
  23. -3- Tie Up Start & End Scenes @BrittBarak

  24. keypad_down keypad_up constraintSet constraintSet layout_call @BrittBarak

  25. keypad_down scene_call keypad_up constraintSet constraintSet layout_call @BrittBarak

  26. <MotionScene ... > <Transition motion:constraintSetStart="@layout/keypad_down" motion:constraintSetEnd="@layout/keypad_up" motion:duration="1000"> <OnClick motion:mode="toggle" motion:target="@id/btn_drag_keypad"

    /> </Transition> </MotionScene> scene_call.xml @BrittBarak
  27. <MotionScene ... > <Transition motion:constraintSetStart="@layout/keypad_down" motion:constraintSetEnd="@layout/keypad_up" motion:duration="1000"> <OnClick motion:mode="toggle" motion:target="@id/btn_drag_keypad"

    /> </Transition> </MotionScene> scene_call.xml @BrittBarak
  28. -4- Tie Up MotionScene & Layout @BrittBarak

  29. <androidx.constraintlayout.motion.widget.MotionLayout android:id=“@+id/motionLayout" app:layoutDescription=“@xml/scene_call"… > … </androidx.constraintlayout.motion.widget.MotionLayout> layout_call.xml @BrittBarak

  30. keypad_down scene_call keypad_up constraintSet constraintSet layout_call @BrittBarak

  31. -5- Define Trigger @BrittBarak

  32. <MotionScene ... > <Transition motion:constraintSetStart="@layout/keypad_down" motion:constraintSetEnd="@layout/keypad_up" motion:duration="1000"> <OnClick motion:mode="toggle" motion:target="@id/btn_drag_keypad"

    /> </Transition> </MotionScene> scene_call.xml @BrittBarak
  33. <MotionScene ... > <Transition ... > <OnClick motion:target=“@id/btn_drag_keypad" motion:mode=“toggle"/> </Transition>

    </MotionScene> scene_call.xml @BrittBarak
  34. <MotionScene ... > <Transition ... > <OnClick motion:target=“@id/btn_drag_keypad" motion:mode=“toggle"/> </Transition>

    </MotionScene> scene_call.xml @BrittBarak
  35. <MotionScene ... > <Transition ... > <OnSwipe motion:touchAnchorId="@id/btn_drag_keypad" motion:dragDirection="dragUp" motion:touchAnchorSide="top"

    /> </Transition> </MotionScene> scene_call.xml @BrittBarak
  36. <MotionScene ... > <Transition ... > <OnSwipe motion:touchAnchorId="@id/btn_drag_keypad" motion:dragDirection="dragUp" motion:touchAnchorSide="top"

    /> </Transition> </MotionScene> scene_call.xml @BrittBarak
  37. <MotionScene ... > <Transition ... > <OnSwipe motion:touchAnchorId="@id/btn_drag_keypad" motion:touchAnchorSide="top" motion:dragDirection=“dragUp"/>

    </Transition> </MotionScene> scene_call.xml @BrittBarak
  38. <MotionScene ... > <Transition ... > <OnSwipe motion:touchAnchorId="@id/btn_drag_keypad" motion:touchAnchorSide="top" motion:dragDirection=“dragUp"/>

    </Transition> </MotionScene> scene_call.xml @BrittBarak
  39. <MotionScene ... > <Transition ... > <OnSwipe motion:touchAnchorId="@id/btn_drag_keypad" motion:touchAnchorSide="top" motion:dragDirection=“dragUp"/>

    </Transition> </MotionScene> scene_call.xml @BrittBarak
  40. And now… MAGIC @BrittBarak

  41. @BrittBarak

  42. Out Of The Box @BrittBarak

  43. Out Of The Box alpha visibility elevation scale X/Y rotation

    X/Y translation X/Y/Z @BrittBarak
  44. And other attributes? @BrittBarak

  45. @BrittBarak

  46. Custom Attributes @BrittBarak

  47. Custom Attributes •Name from getter / setter •Type •Color •Dimension

    •Integer •Float •String •Boolean @BrittBarak
  48. A little prep work @BrittBarak

  49. keypad_down scene_call keypad_up constraintSet constraintSet layout_call @BrittBarak

  50. scene_call keypad_down keypad_up constraintSet constraintSet layout_call @BrittBarak

  51. <MotionScene ... > <Transition ... motion:constraintSetStart= "@layout/keypad_down" motion:constraintSetEnd =“@layout/keypad_up” >

    <OnClick motion:mode="toggle" motion:target="@id/btn_drag_keypad" /> </Transition> </MotionScene> scene_call.xml @BrittBarak
  52. <MotionScene ... > <Transition ... motion:constraintSetStart= "@layout/keypad_down" motion:constraintSetEnd =“@layout/keypad_up” >

    <OnClick motion:mode="toggle" motion:target="@id/btn_drag_keypad" /> </Transition> </MotionScene> scene_call.xml @BrittBarak
  53. <MotionScene ... > <Transition ... motion:constraintSetStart= "@id/keypad_down" motion:constraintSetEnd =“@id/keypad_up” >

    <OnClick motion:mode="toggle" motion:target="@id/btn_drag_keypad" /> </Transition> </MotionScene> scene_call.xml @BrittBarak
  54. <MotionScene ... > <Transition ... /> <ConstraintSet android:id=“@+id/keypad_down”> </ConstraintSet> <ConstraintSet

    android:id="@+id/keypad_up"> </ConstraintSet> </MotionScene> scene_call.xml @BrittBarak
  55. <MotionScene ... > <Transition ... /> <ConstraintSet android:id=“@+id/keypad_down”> </ConstraintSet> <ConstraintSet

    android:id="@+id/keypad_up"> </ConstraintSet> </MotionScene> scene_call.xml @BrittBarak
  56. <MotionScene ... > <Transition ... /> <ConstraintSet android:id=“@+id/keypad_down”> </ConstraintSet> </MotionScene>

    scene_call.xml @BrittBarak
  57. <MotionScene ... > <Transition ... /> <ConstraintSet android:id=“@+id/keypad_down”> </ConstraintSet> </MotionScene>

    keypad_down constraintSet scene_call.xml @BrittBarak
  58. layout/keypad_down.xml <View> keypad_down constraintSet @BrittBarak

  59. scene_call.xml <Constraint> keypad_down constraintSet layout/keypad_down.xml <View> keypad_down constraintSet @BrittBarak

  60. scene_call.xml <Constraint> keypad_down constraintSet layout/keypad_down.xml <View> keypad_down constraintSet @BrittBarak

  61. layout/keypad_down.xml <View> keypad_down constraintSet scene_call.xml <Constraint> keypad_down constraintSet @BrittBarak

  62. <MotionScene ... > <Transition ... /> <ConstraintSet android:id=“@+id/keypad_down”> </ConstraintSet> </MotionScene>

    scene_call.xml @BrittBarak
  63. <MotionScene ... > <Transition ... /> <ConstraintSet android:id=“@+id/keypad_down”> <Constraint …/>

    <Constraint …/> <Constraint …/> </ConstraintSet> </MotionScene> scene_call.xml @BrittBarak
  64. <MotionScene ... > <Transition ... /> <ConstraintSet android:id=“@+id/keypad_down”> <Constraint …/>

    <Constraint …/> <Constraint …/> </ConstraintSet> </MotionScene> scene_call.xml @BrittBarak
  65. <MotionScene ... > <Transition ... /> <ConstraintSet android:id=“@+id/keypad_down”> <Constraint android:id=“@id/iv_avatar"

    android:layout_width="@drawable/avatar" android:layout_height="@drawable/avatar" motion: layout_constraintStart_toStartOf="parent" motion: layout_constraintTop_toTopOf=“parent”…/> </ConstraintSet> </MotionScene> scene_call.xml @BrittBarak
  66. <MotionScene ... > <Transition ... /> <ConstraintSet android:id=“@+id/keypad_down”> <Constraint android:id=“@id/iv_avatar"

    android:layout_width="@drawable/avatar" android:layout_height="@drawable/avatar" motion: layout_constraintStart_toStartOf="parent" motion: layout_constraintTop_toTopOf=“parent”…/> </ConstraintSet> </MotionScene> scene_call.xml @BrittBarak
  67. <MotionScene ... > <Transition ... /> <ConstraintSet android:id=“@+id/keypad_down”> <Constraint android:id=“@id/iv_avatar"

    android:layout_width="@drawable/avatar" android:layout_height="@drawable/avatar" motion: layout_constraintStart_toStartOf="parent" …/> </ConstraintSet> </MotionScene> scene_call.xml @BrittBarak
  68. remember: constraints are rewritten @BrittBarak

  69. And now… MAGIC @BrittBarak

  70. And now… (same) MAGIC @BrittBarak

  71. @BrittBarak

  72. And the custom attribute! @BrittBarak

  73. <Constraint android:id=“@id/name" android:layout_width="match_parent" android:layout_height="wrap_content" ... > <CustomAttribute motion:attributeName="textSize" motion:customDimension=“@dimen/small_name“/ >

    </Constraint> scene_call.xml @BrittBarak
  74. <Constraint android:id="@id/name" ... > <CustomAttribute motion:attributeName="textSize" motion:customDimension=“@dimen/name_big“/> </Constraint> scene_call.xml @BrittBarak

  75. scene_call.xml keypad_down keypad_up @BrittBarak

  76. constraint: @id/name attribute textSize scene_call.xml keypad_down constraint: @id/name attribute textSize

    keypad_up @BrittBarak
  77. scene_call.xml keypad_down constraint: @id/name attribute textSize keypad_up constraint: @id/name attribute

    textSize @BrittBarak
  78. And now… MAGIC @BrittBarak

  79. And now… MAGIC @BrittBarak

  80. Custom Attributes •customColorValue •customDimension •customIntegerValue •customFloatValue •customStringValue •customBoolean @BrittBarak

  81. Images @BrittBarak

  82. ImageView —> ImageFilterView @BrittBarak

  83. Filter Image Attributes •saturation •contrast •warmth •crossfade @BrittBarak

  84. Image Attributes •saturation •0 = grayscale —> 1 = original

    —> 2 = hyper saturated •contrast •0= gray —> 1 = unchanged —> 2 = high contrast •warmth •0.5 = cold (blue tint) —>1 = neutral —> 2 = warm (red tint) •crossfade •0 = src —> 1 = app:altSrc @BrittBarak
  85. <Constraint android:id=“@id/iv_avatar” ... > <CustomAttribute motion:attributeName="saturation" motion:customFloatValue="0.2"/> </Constraint> @BrittBarak

  86. ConstraintSet : keypad_down <Constraint android:id=“@id/iv_avatar” ... > <CustomAttribute motion:attributeName="saturation" motion:customFloatValue=“1.5”/>

    </Constraint> @BrittBarak
  87. ConstraintSet : keypad_up <Constraint android:id=“@id/iv_avatar” ... > <CustomAttribute motion:attributeName="saturation" motion:customFloatValue="0.2"/>

    </Constraint> @BrittBarak
  88. @BrittBarak

  89. Recap 1. Create a MotionLayout 2. Create MotionScene 3. Define

    ConstraintSet Start & ConstraintSet End •In Layout •In MotionScene 4. Tie up Layout & MotionScene 5. CustomAttributes & ImageFilterView @BrittBarak
  90. Recap 1. Create a MotionLayout 2. Create MotionScene 3. Define

    ConstraintSet Start & ConstraintSet End •In Layout •In MotionScene 4. Tie up Layout & MotionScene 5. CustomAttributes & ImageFilterView @BrittBarak
  91. Recap 1. Create a MotionLayout 2. Create MotionScene 3. Define

    ConstraintSet Start & ConstraintSet End •In Layout •In MotionScene 4. Tie up Layout & MotionScene 5. CustomAttributes & ImageFilterView @BrittBarak
  92. Recap 1. Create a MotionLayout 2. Create MotionScene 3. Define

    ConstraintSet Start & ConstraintSet End •In Layout •In MotionScene 4. Tie up Layout & MotionScene 5. CustomAttributes & ImageFilterView @BrittBarak
  93. Recap 1. Create a MotionLayout 2. Create MotionScene 3. Define

    ConstraintSet Start & ConstraintSet End •In Layout •In MotionScene 4. Tie up Layout & MotionScene 5. CustomAttributes & ImageFilterView @BrittBarak
  94. Recap 1. Create a MotionLayout 2. Create MotionScene 3. Define

    ConstraintSet Start & ConstraintSet End •In Layout •In MotionScene 4. Tie up Layout & MotionScene 5. CustomAttributes & ImageFilterView @BrittBarak
  95. Recap 1. Create a MotionLayout 2. Create MotionScene 3. Define

    ConstraintSet Start & ConstraintSet End •In Layout •In MotionScene 4. Tie up Layout & MotionScene 5. CustomAttributes & ImageFilterView @BrittBarak
  96. There’s a problem @BrittBarak

  97. @BrittBarak

  98. None
  99. Checkout this example @BrittBarak

  100. @BrittBarak

  101. @BrittBarak

  102. Start with 2 states @BrittBarak

  103. Start with 2 states @BrittBarak

  104. Start with 2 states • MotionLayout • MotionScene • ConstraintSets:

    Start & End @BrittBarak
  105. Out Of The Box @BrittBarak

  106. Out Of The Box •Icons scale •Indicator position @BrittBarak

  107. Custom Attributes @BrittBarak

  108. Custom Attributes •backgroundColor @BrittBarak

  109. backgroundColor <Constraint android:id="@id/indicator" ... > <CustomAttribute motion:attributeName="backgroundColor" motion:customColorValue="@color/color_start" /> </Constraint>

    @BrittBarak
  110. Custom Attributes •backgroundColor •Icon color @BrittBarak

  111. Custom Attributes •backgroundColor •Icon color —> crossfade @BrittBarak

  112. crossfade <…ImageFilterView ... android:src="@drawable/ic_chats_black" motion:altSrc="@drawable/ic_chats_gray"/> @BrittBarak Layout

  113. Crossfade <Constraint android:id=“@id/ic_chats” ... > <CustomAttribute motion:attributeName="crossfade" motion:customFloatValue=“0" /> </Constraint>

    @BrittBarak MotionScene
  114. And now… half-way MAGIC @BrittBarak

  115. @BrittBarak

  116. How to define a middle state? @BrittBarak

  117. KeyFrames! @BrittBarak

  118. <MotionScene ... > <Transition ... > </Transition> </MotionScene> scene_tabs.xml @BrittBarak

  119. <MotionScene ... > <Transition ... > <KeyFrameSet> </KeyFrameSet> </Transition> </MotionScene>

    scene_tabs.xml @BrittBarak
  120. <MotionScene ... > <Transition ... > <KeyFrameSet> </KeyFrameSet> </Transition> </MotionScene>

    scene_tabs.xml KeyFrame: per View at a frame @BrittBarak
  121. Icon Scale @BrittBarak

  122. <KeyFrameSet> <KeyAttribute motion:framePosition=“50" motion:target=“@id/ic_calls" android:scaleX=“2” motion:scaleY=“2"/> </KeyFrameSet> scene_tabs.xml @BrittBarak

  123. <KeyFrameSet> <KeyAttribute motion:framePosition=“50" motion:target=“@id/ic_calls" android:scaleX=“2” motion:scaleY=“2"/> </KeyFrameSet> scene_tabs.xml @BrittBarak

  124. <KeyFrameSet> <KeyAttribute motion:framePosition=“50" motion:target=“@id/ic_calls" android:scaleX=“2” motion:scaleY=“2"/> </KeyFrameSet> scene_tabs.xml @BrittBarak

  125. Indicator Color @BrittBarak

  126. <KeyFrameSet> <KeyAttribute motion:framePosition="50" motion:target="@id/indicator"> <CustomAttribute motion:attributeName="backgroundColor" motion:customColorValue="@color/yellow" /> </KeyAttribute> </KeyFrameSet>

    scene_tabs.xml @BrittBarak
  127. <KeyFrameSet> <KeyAttribute motion:framePosition="50" motion:target="@id/indicator"> <CustomAttribute motion:attributeName="backgroundColor" motion:customColorValue="@color/yellow" /> </KeyAttribute> </KeyFrameSet>

    scene_tabs.xml @BrittBarak
  128. <KeyFrameSet> <KeyAttribute motion:framePosition="50" motion:target="@id/indicator"> <CustomAttribute motion:attributeName="backgroundColor" motion:customColorValue="@color/yellow" /> </KeyAttribute> </KeyFrameSet>

    scene_tabs.xml @BrittBarak
  129. <KeyFrameSet> <KeyAttribute motion:framePosition="50" motion:target="@id/indicator"> <CustomAttribute motion:attributeName="backgroundColor" motion:customColorValue="@color/yellow" /> </KeyAttribute> </KeyFrameSet>

    scene_tabs.xml @BrittBarak
  130. None
  131. Hook up to viewPager @BrittBarak

  132. Activity / Fragment listener = object : ViewPager.OnPageChangeListener { override

    fun onPageScrolled(…) { motionLayout.progress = (position + positionOffset) / (viewpager.adapter!!.count - 1) } } viewpager.addOnPageChangeListener(listener) @BrittBarak
  133. Activity / Fragment listener = object : ViewPager.OnPageChangeListener { override

    fun onPageScrolled(…) { motionLayout.progress = (position + positionOffset) / (viewpager.adapter!!.count - 1) } } viewpager.addOnPageChangeListener(listener) @BrittBarak
  134. Activity / Fragment listener = object : ViewPager.OnPageChangeListener { override

    fun onPageScrolled(…) { motionLayout.progress = (position + positionOffset) / (viewpager.adapter!!.count - 1) } } viewpager.addOnPageChangeListener(listener) @BrittBarak
  135. Activity / Fragment listener = object : ViewPager.OnPageChangeListener { override

    fun onPageScrolled(…) { motionLayout.progress = (position + positionOffset) / (viewpager.adapter!!.count - 1) } } viewpager.addOnPageChangeListener(listener) @BrittBarak
  136. Activity / Fragment listener = object : ViewPager.OnPageChangeListener { override

    fun onPageScrolled(…) { motionLayout.progress = (position + positionOffset) / (viewpager.adapter!!.count - 1) } } viewpager.addOnPageChangeListener(listener) @BrittBarak
  137. And now… MAGIC! @BrittBarak

  138. And now… MAGIC! @BrittBarak

  139. How to make your CURRENT app dance with MotionLayout? Gif:

    @Opintrius @BrittBarak
  140. How to DANCE with MotionLayout? 1. Setup Layout 1. Wrap

    with MotionLayout 2. Extract views to upper level layout @BrittBarak
  141. How to DANCE with MotionLayout? 2. Define Start & Ends

    Scenes 1. In Layouts 2. Extract the constraints into MotionScene layout Start End @BrittBarak
  142. How to DANCE with MotionLayout? 2. Define Start & Ends

    Scenes 1. In Layouts 2. Extract the constraints into MotionScene Start End Scene layout @BrittBarak
  143. constraintSet constraintSet How to DANCE with MotionLayout? 2. Define Start

    & Ends Scenes 1. In Layouts 2. Extract the constraints into MotionScene Start End Scene layout @BrittBarak
  144. layout/keypad_down.xml <View> keypad_down constraintSet scene_call.xml <Constraint> keypad_down constraintSet @BrittBarak

  145. constraintSet constraintSet How to DANCE with MotionLayout? 2. Define Start

    & Ends Scenes 1. In Layouts 2. Extract the constraints into MotionScene Start End Scene layout @BrittBarak
  146. Scene Transition ConstraintSet ConstraintSet @BrittBarak

  147. Scene Transition ConstraintSet ConstraintSet Triggers @BrittBarak

  148. Scene Transition Triggers ConstraintSet @BrittBarak

  149. Scene Transition Triggers ConstraintSet CustomAttributes @BrittBarak

  150. Scene Transition Triggers ConstraintSet CustomAttributes KeyFrames @BrittBarak

  151. Make MAGIC! @BrittBarak

  152. Resources •Big THANK YOU John Hoford & Nicolas Road!! @BrittBarak

  153. Resources •Big THANK YOU John Hoford & Nicolas Road!! @BrittBarak

  154. Resources •Big THANK YOU John Hoford & Nicolas Road!! •Blog

    Medium posts series by Nicolas @BrittBarak
  155. Resources •Big THANK YOU John Hoford & Nicolas Road!! •Blog

    Medium posts series by Nicolas • And… I’ll share mine soon! Promise @BrittBarak
  156. Resources •Big THANK YOU John Hoford & Nicolas Road!! •Blog

    Medium posts series by Nicolas • And… I’ll share mine soon! Promise @BrittBarak
  157. Thank you! Keep in touch! Britt Barak @brittBarak