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

ConstraintLayout 2.0 / MotionLayout

ConstraintLayout 2.0 / MotionLayout

Presentation on MotionLayout at 360 AnDev 2018 in Denver

Avatar for Nicolas Roard

Nicolas Roard

July 20, 2018
Tweet

More Decks by Nicolas Roard

Other Decks in Programming

Transcript

  1. { 360 | AnDev } 2018 ConstraintLayout 2.0 ★ Layout

    ★ Helpers ★ Rendering ★ Live Resize
  2. { 360 | AnDev } 2018 ConstraintLayout 2.0 ★ Layout

    ★ Helpers ★ Rendering ★ Live Resize ★ Motion
  3. { 360 | AnDev } 2018 ConstraintLayout 2.0 ★ Layout

    ★ Helpers ★ Rendering ★ Live Resize ★ Motion ★ API
  4. { 360 | AnDev } 2018 ConstraintLayout 2.0 ★ Layout

    ★ Helpers ★ Rendering ★ Live Resize ★ Motion ★ API
  5. { 360 | AnDev } 2018 MotionLayout: Why ★ Why

    ★ Audience ★ What can it do
  6. { 360 | AnDev } 2018 Animation Types Animated content

    Transition Layouts Motion Property Animation
  7. { 360 | AnDev } 2018 Animation Types Animated content

    Transition Layouts Motion Lottie, Kyrie, Animated Vector Drawable, GIFs, etc. TransitionManager CoordinatorLayout Property Animation Property animation framework (code)
  8. { 360 | AnDev } 2018 MotionLayout Animated content Transition

    Layouts Motion Lottie, Kyrie, Animated Vector Drawable, GIFs, etc. TransitionManager CoordinatorLayout Property Animation Property animation framework (code)
  9. { 360 | AnDev } 2018 Declarative Approach ★ Better

    & Easier model ★ We can build tooling
  10. { 360 | AnDev } 2018 Declarative Approach ★ Better

    & Easier model ★ We can build tooling
  11. { 360 | AnDev } 2018 Key Concepts ★ Transition

    ★ Events ★ Keyframes ★ Motion
  12. { 360 | AnDev } 2018 ConstraintSet ★ Encapsulate all

    the rules for a layout ★ You can apply ConstraintSet to an existing layout ★ You can switch between multiple ConstraintSets ★ With TransitionManager, basic animation capabilities
  13. { 360 | AnDev } 2018 Start End Seekable Transition

    Start ConstraintSet End ConstraintSet Interpolation
  14. <?xml version="1.0" encoding="utf-8"?> <MotionScene xmlns:android="http://schemas.android.com/apk/res/android" xmlns:motion="http://schemas.android.com/apk/res-auto"> <Transition motion:constraintSetStart="@+id/start" motion:constraintSetEnd="@+id/end" motion:duration="1000">

    </Transition> <ConstraintSet android:id="@+id/start"> <Constraint android:id="@+id/button" android:layout_width="64dp" android:layout_height="64dp" android:layout_marginStart="8dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintStart_toStartOf="parent" motion:layout_constraintTop_toTopOf="parent" />
  15. <?xml version="1.0" encoding="utf-8"?> <MotionScene xmlns:android="http://schemas.android.com/apk/res/android" xmlns:motion="http://schemas.android.com/apk/res-auto"> <Transition motion:constraintSetStart="@+id/start" motion:constraintSetEnd="@+id/end" motion:duration="1000">

    </Transition> <ConstraintSet android:id="@+id/start"> <Constraint android:id="@+id/button" android:layout_width="64dp" android:layout_height="64dp" android:layout_marginStart="8dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintStart_toStartOf="parent" motion:layout_constraintTop_toTopOf="parent" />
  16. motion:constraintSetStart="@+id/start" motion:constraintSetEnd="@+id/end" motion:duration="1000"> </Transition> <ConstraintSet android:id="@+id/start"> <Constraint android:id="@+id/button" android:layout_width="64dp" android:layout_height="64dp"

    android:layout_marginStart="8dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintStart_toStartOf="parent" motion:layout_constraintTop_toTopOf="parent" /> </ConstraintSet> <ConstraintSet android:id="@+id/end"> <Constraint android:id="@+id/button" android:layout_width="64dp"
  17. motion:constraintSetStart="@+id/start" motion:constraintSetEnd="@+id/end" motion:duration="1000"> </Transition> <ConstraintSet android:id="@+id/start"> <Constraint android:id="@+id/button" android:layout_width="64dp" android:layout_height="64dp"

    android:layout_marginStart="8dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintStart_toStartOf="parent" motion:layout_constraintTop_toTopOf="parent" /> </ConstraintSet> <ConstraintSet android:id="@+id/end"> <Constraint android:id="@+id/button" android:layout_width="64dp"
  18. motion:constraintSetStart="@+id/start" motion:constraintSetEnd="@+id/end" motion:duration="1000"> </Transition> <ConstraintSet android:id="@+id/start"> <Constraint android:id="@+id/button" android:layout_width="64dp" android:layout_height="64dp"

    android:layout_marginStart="8dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintStart_toStartOf="parent" motion:layout_constraintTop_toTopOf="parent" /> </ConstraintSet> <ConstraintSet android:id="@+id/end"> <Constraint android:id="@+id/button" android:layout_width="64dp"
  19. android:layout_marginStart="8dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintStart_toStartOf="parent" motion:layout_constraintTop_toTopOf="parent" /> </ConstraintSet> <ConstraintSet android:id="@+id/end"> <Constraint android:id="@+id/button"

    android:layout_width="64dp" android:layout_height="64dp" android:layout_marginEnd="8dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintEnd_toEndOf="parent" motion:layout_constraintTop_toTopOf="parent" /> </ConstraintSet> </MotionScene>
  20. android:layout_marginStart="8dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintStart_toStartOf="parent" motion:layout_constraintTop_toTopOf="parent" /> </ConstraintSet> <ConstraintSet android:id="@+id/end"> <Constraint android:id="@+id/button"

    android:layout_width="64dp" android:layout_height="64dp" android:layout_marginEnd="8dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintEnd_toEndOf="parent" motion:layout_constraintTop_toTopOf="parent" /> </ConstraintSet> </MotionScene>
  21. android:layout_marginStart="8dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintStart_toStartOf="parent" motion:layout_constraintTop_toTopOf="parent" /> </ConstraintSet> <ConstraintSet android:id="@+id/end"> <Constraint android:id="@+id/button"

    android:layout_width="64dp" android:layout_height="64dp" android:layout_marginEnd="8dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintEnd_toEndOf="parent" motion:layout_constraintTop_toTopOf="parent" /> </ConstraintSet> </MotionScene>
  22. android:layout_height="match_parent"> <View android:id="@+id/button" android:background="@color/colorAccent" android:layout_width="64dp" android:layout_height=“64dp"/> </android.support.constraint.motion.MotionLayout> <Button android:id=“@+id/run" android:layout_width="wrap_content"

    android:layout_height="wrap_content" android:layout_marginBottom="8dp" android:layout_marginEnd="8dp" android:text="Run" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" />
  23. class BasicTransitionActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) {

    super.onCreate(savedInstanceState) setContentView(R.layout.motion) run.setOnClickListener { motionLayout.transitionToEnd() } } }
  24. <?xml version="1.0" encoding="utf-8"?> <MotionScene xmlns:android="http://schemas.android.com/apk/res/android" xmlns:motion="http://schemas.android.com/apk/res-auto"> <Transition motion:constraintSetStart="@+id/start" motion:constraintSetEnd="@+id/end" motion:duration="1000">

    </Transition> <ConstraintSet android:id="@+id/start"> <Constraint android:id="@+id/button" android:layout_width="64dp" android:layout_height="64dp" android:layout_marginStart="8dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintStart_toStartOf="parent" motion:layout_constraintTop_toTopOf="parent" />
  25. <?xml version="1.0" encoding="utf-8"?> <MotionScene xmlns:android="http://schemas.android.com/apk/res/android" xmlns:motion="http://schemas.android.com/apk/res-auto"> <Transition motion:constraintSetStart="@+id/start" motion:constraintSetEnd="@+id/end" motion:duration="1000">

    </Transition> <ConstraintSet android:id="@+id/start"> <Constraint android:id="@+id/button" android:layout_width="64dp" android:layout_height="64dp" android:layout_marginStart="8dp" motion:layout_constraintBottom_toBottomOf="parent"
  26. <?xml version="1.0" encoding="utf-8"?> <MotionScene xmlns:android="http://schemas.android.com/apk/res/android" xmlns:motion="http://schemas.android.com/apk/res-auto"> <Transition motion:constraintSetStart="@+id/start" motion:constraintSetEnd="@+id/end" motion:duration="1000">

    </Transition> <ConstraintSet android:id="@+id/start"> <Constraint android:id="@+id/button" android:layout_width="64dp" android:layout_height="64dp" android:layout_marginStart="8dp" motion:layout_constraintBottom_toBottomOf="parent" <OnClick motion:target=“@id/run"/>
  27. xmlns:motion="http://schemas.android.com/apk/res-auto"> <Transition motion:constraintSetStart="@+id/start" motion:constraintSetEnd="@+id/end" motion:duration="1000"> </Transition> <ConstraintSet android:id="@+id/start"> <Constraint android:id="@+id/button"

    android:layout_width="64dp" android:layout_height="64dp" android:layout_marginStart="8dp" <OnSwipe motion:dragDirection="dragRight" motion:touchAnchorId="@id/button" motion:touchAnchorSide="right" />
  28. { 360 | AnDev } 2018 MotionLayout XML attributes ★

    app:layoutDescription=”reference” ★ app:applyMotionScene=”boolean” [ default = true ] ★ app:showPaths=”boolean” [ default = false] ★ app:progress=”float” ★ app:currentState=”reference”
  29. { 360 | AnDev } 2018 Interpolated Attributes ★ Position,

    Dimensions ★ Visibility & Alpha ★ Translation, Rotation, Scale, Elevation ★ Custom attributes
  30. { 360 | AnDev } 2018 Custom Attributes ★ Extension

    to ConstraintSet ★ Define values for any attribute ★ Specify the type ★ Specify the setter name string color integer float dimension boolean
  31. { 360 | AnDev } 2018 Utilities ★ MockView ★

    ImageFilterView : Contrast, Saturation, Warmth, Crossfade
  32. <MotionScene xmlns:android="http://schemas.android.com/apk/res/android" xmlns:motion="http://schemas.android.com/apk/res-auto"> <Transition motion:constraintSetStart="@+id/start" motion:constraintSetEnd="@+id/end" motion:duration="1000"> <OnSwipe motion:dragDirection="dragRight" motion:touchAnchorId="@id/image"

    motion:touchAnchorSide="right" /> </Transition> <ConstraintSet android:id="@+id/start"> <Constraint android:id="@+id/image" android:layout_width="100dp" android:layout_height="100dp" android:layout_marginStart="8dp"
  33. motion:touchAnchorSide="right" /> </Transition> <ConstraintSet android:id="@+id/start"> <Constraint android:id="@+id/image" android:layout_width="100dp" android:layout_height="100dp" android:layout_marginStart="8dp"

    motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintStart_toStartOf="parent" motion:layout_constraintTop_toTopOf="parent"> <CustomAttribute motion:attributeName="Crossfade" motion:customFloatValue="0" /> </Constraint> </ConstraintSet> <ConstraintSet android:id="@+id/end"> <Constraint
  34. motion:touchAnchorSide="right" /> </Transition> <ConstraintSet android:id="@+id/start"> <Constraint android:id="@+id/image" android:layout_width="100dp" android:layout_height="100dp" android:layout_marginStart="8dp"

    motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintStart_toStartOf="parent" motion:layout_constraintTop_toTopOf="parent"> <CustomAttribute motion:attributeName="Crossfade" motion:customFloatValue="0" /> </Constraint> </ConstraintSet> <ConstraintSet android:id="@+id/end"> <Constraint
  35. </Constraint> </ConstraintSet> <ConstraintSet android:id="@+id/end"> <Constraint android:id="@id/image" android:layout_width="100dp" android:layout_height="100dp" android:layout_marginEnd="8dp" motion:layout_constraintBottom_toBottomOf="parent"

    motion:layout_constraintEnd_toEndOf="parent" motion:layout_constraintTop_toTopOf="parent"> <CustomAttribute motion:attributeName="Crossfade" motion:customFloatValue="1" /> </Constraint> </ConstraintSet> </MotionScene>
  36. </Constraint> </ConstraintSet> <ConstraintSet android:id="@+id/end"> <Constraint android:id="@id/image" android:layout_width="100dp" android:layout_height="100dp" android:layout_marginEnd="8dp" motion:layout_constraintBottom_toBottomOf="parent"

    motion:layout_constraintEnd_toEndOf="parent" motion:layout_constraintTop_toTopOf="parent"> <CustomAttribute motion:attributeName="Crossfade" motion:customFloatValue="1" /> </Constraint> </ConstraintSet> </MotionScene>
  37. { 360 | AnDev } 2018 Transition API ★ transitionToEnd()

    ★ transitionToStart() ★ transitionToState(int state) ★ setProgress(float value) [0 .. 1]
  38. public interface TransitionListener { void onTransitionChange(MotionLayout motionLayout, int startId, int

    endId, float progress); void onTransitionCompleted(MotionLayout motionLayout, int currentId); }
  39. Touch Up / Release Takes in account velocity Choose a

    continuous velocity curve to reach the endpoints with a velocity of zero
  40. Touch Up / Release Takes in account velocity Choose a

    continuous velocity curve to reach the endpoints with a velocity of zero
  41. { 360 | AnDev } 2018 Keyframes ★ Position ★

    Attributes ★ Cycles ★ …and more
  42. KeyAttributes support motion:transitionEasing motion:curveFit android:visibility android:alpha android:elevation android:rotation android:rotationX android:rotationY

    android:scaleX android:scaleY android:translationX android:translationY android:translationZ motion:transitionPathRotate motion:progress + Custom Attributes <CustomAttribute motion:attributeName="BackgroundColor" motion:customColorValue="#D81B60"/>
  43. KeyCycle <KeyFrameSet> <KeyPosition…/> <KeyAttributes…/> <KeyAttributes…/> <KeyCycle motion:target="@+id/widget" motion:framePosition="0" motion:wavePeriod=“0” motion:translationX=“0.0"

    /> <KeyCycle motion:target="@+id/widget" motion:framePosition="50" motion:wavePeriod=“50” motion:translationX=“30dp" /> </KeyFrameSet>
  44. KeyCycle <KeyFrameSet> <KeyPosition…/> <KeyAttributes…/> <KeyAttributes…/> <KeyCycle motion:target="@+id/widget" motion:framePosition="0" motion:wavePeriod=“0” motion:translationX=“0.0"

    /> <KeyCycle motion:target="@+id/widget" motion:framePosition="50" motion:wavePeriod=“50” motion:translationX=“30dp" /> </KeyFrameSet>
  45. KeyCycle <KeyFrameSet> <KeyPosition…/> <KeyAttributes…/> <KeyAttributes…/> <KeyCycle motion:target="@+id/widget" motion:framePosition="0" motion:wavePeriod=“0” motion:translationX=“0.0"

    /> <KeyCycle motion:target="@+id/widget" motion:framePosition="50" motion:wavePeriod=“50” motion:translationX=“30dp" /> </KeyFrameSet>
  46. KeyCycle <KeyFrameSet> <KeyPosition…/> <KeyAttributes…/> <KeyAttributes…/> <KeyCycle motion:target="@+id/widget" motion:framePosition="0" motion:wavePeriod=“0” motion:translationX=“0.0"

    /> <KeyCycle motion:target="@+id/widget" motion:framePosition="50" motion:wavePeriod=“50” motion:translationX=“30dp" /> </KeyFrameSet>
  47. { 360 | AnDev } 2018 Motion ★ CoordinatorLayout ★

    DrawerLayout ★ ViewPager ★ MotionLayout
  48. class CollapsibleToolbar @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null,

    defStyleAttr: Int = 0 ) : MotionLayout(context, attrs, defStyleAttr), AppBarLayout.OnOffsetChangedListener { override fun onOffsetChanged(appBarLayout: AppBarLayout?, verticalOffset: Int) { progress = -verticalOffset / appBarLayout?.totalScrollRange?.toFloat()!! } override fun onAttachedToWindow() { super.onAttachedToWindow() (parent as? AppBarLayout)?.addOnOffsetChangedListener(this) } }
  49. class CollapsibleToolbar @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null,

    defStyleAttr: Int = 0 ) : MotionLayout(context, attrs, defStyleAttr), AppBarLayout.OnOffsetChangedListener { override fun onOffsetChanged(appBarLayout: AppBarLayout?, verticalOffset: Int) { progress = -verticalOffset / appBarLayout?.totalScrollRange?.toFloat()!! } override fun onAttachedToWindow() { super.onAttachedToWindow() (parent as? AppBarLayout)?.addOnOffsetChangedListener(this) } }
  50. <?xml version="1.0" encoding="utf-8"?> <com.google.androidstudio.motionlayoutexample.utils.CollapsibleToolbar xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/motionLayout" app:layoutDescription="@xml/scene_09" android:layout_width="match_parent"

    android:layout_height="match_parent" android:minHeight="50dp" android:fitsSystemWindows="false" app:layout_scrollFlags="scroll|enterAlways|snap|exitUntilCollapsed"> <ImageView android:id="@+id/background" android:layout_width="match_parent" android:layout_height="200dp" android:background="@color/colorAccent" android:scaleType="centerCrop"
  51. <ImageView android:id="@+id/background" android:layout_width="match_parent" android:layout_height="200dp" android:background="@color/colorAccent" android:scaleType="centerCrop" android:src="@drawable/monterey"/> <TextView android:id="@+id/label" android:layout_width="wrap_content"

    android:layout_height="wrap_content" android:transformPivotX="0dp" android:transformPivotY="0dp" android:text="Monterey" android:textColor="#FFF" android:textSize="32dp" /> </com.google.androidstudio.motionlayoutexample.utils.CollapsibleToolbar>
  52. <?xml version="1.0" encoding="utf-8"?> <MotionScene xmlns:android="http://schemas.android.com/apk/res/android" xmlns:motion="http://schemas.android.com/apk/res-auto"> <Transition motion:constraintSetStart="@+id/start" motion:constraintSetEnd="@+id/end" />

    <ConstraintSet android:id="@+id/start"> <Constraint android:id="@+id/background" android:layout_width="match_parent" android:layout_height="match_parent" android:alpha="1.0" motion:layout_constraintBottom_toBottomOf="parent"/> <Constraint android:id="@+id/label" android:layout_width="wrap_content"
  53. <ConstraintSet android:id="@+id/start"> <Constraint android:id="@+id/background" android:layout_width="match_parent" android:layout_height="match_parent" android:alpha="1.0" motion:layout_constraintBottom_toBottomOf="parent"/> <Constraint android:id="@+id/label"

    android:layout_width="wrap_content" android:layout_height="wrap_content" android:rotation="-90.0" motion:layout_constraintBottom_toBottomOf="@+id/background" motion:layout_constraintStart_toStartOf="parent"/> </ConstraintSet> <ConstraintSet android:id="@+id/end"> <Constraint android:id="@+id/background"
  54. <ConstraintSet android:id="@+id/end"> <Constraint android:id="@+id/background" android:layout_width="match_parent" android:layout_height="match_parent" android:alpha="0.2" motion:layout_constraintBottom_toBottomOf="parent"/> <Constraint android:id="@+id/label"

    android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:layout_marginBottom="8dp" android:rotation="0.0" motion:layout_constraintBottom_toBottomOf="@+id/background" motion:layout_constraintStart_toStartOf="parent" /> </ConstraintSet> </MotionScene>
  55. class DrawerContent @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null,

    defStyleAttr: Int = 0 ) : MotionLayout(context, attrs, defStyleAttr), DrawerLayout.DrawerListener { override fun onDrawerStateChanged(newState: Int) { } override fun onDrawerSlide(drawerView: View, slideOffset: Float) { progress = slideOffset } override fun onDrawerClosed(drawerView: View) { } override fun onDrawerOpened(drawerView: View) { } override fun onAttachedToWindow() { super.onAttachedToWindow() (parent as? DrawerLayout)?.addDrawerListener(this) } }
  56. class DrawerContent @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null,

    defStyleAttr: Int = 0 ) : MotionLayout(context, attrs, defStyleAttr), DrawerLayout.DrawerListener { override fun onDrawerStateChanged(newState: Int) { } override fun onDrawerSlide(drawerView: View, slideOffset: Float) { progress = slideOffset } override fun onDrawerClosed(drawerView: View) { } override fun onDrawerOpened(drawerView: View) { } override fun onAttachedToWindow() { super.onAttachedToWindow() (parent as? DrawerLayout)?.addDrawerListener(this) } }
  57. class DrawerContent @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null,

    defStyleAttr: Int = 0 ) : MotionLayout(context, attrs, defStyleAttr), DrawerLayout.DrawerListener { override fun onDrawerStateChanged(newState: Int) { } override fun onDrawerSlide(drawerView: View, slideOffset: Float) { progress = slideOffset } override fun onDrawerClosed(drawerView: View) { } override fun onDrawerOpened(drawerView: View) { } override fun onAttachedToWindow() { super.onAttachedToWindow() (parent as? DrawerLayout)?.addDrawerListener(this) } }
  58. class ViewpagerHeader @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null,

    defStyleAttr: Int = 0 ) : MotionLayout(context, attrs, defStyleAttr), ViewPager.OnPageChangeListener { override fun onPageScrollStateChanged(state: Int) {} override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) { var numPages = 3 progress = (position + positionOffset) / (numPages - 1) } override fun onPageSelected(position: Int) {} }
  59. <android.support.constraint.motion.MotionLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto" app:layoutDescription="@xml/scene_19"> <include layout="@layout/motion_19_coordination_header" /> <include

    layout="@layout/content_scrolling" /> <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_add_a_photo_24dp"/> </android.support.constraint.motion.MotionLayout>
  60. <MotionScene xmlns:android="http://schemas.android.com/apk/res/android" xmlns:motion="http://schemas.android.com/apk/res-auto"> <Transition motion:constraintSetEnd="@+id/end" motion:constraintSetStart="@+id/start" motion:duration="250" motion:interpolator="linear"> <OnSwipe motion:touchAnchorId="@+id/motionLayout"

    motion:touchAnchorSide="bottom" motion:dragDirection="dragUp" /> <ConstraintSet android:id="@+id/start"> <Constraint android:id="@id/motionLayout" android:layout_width="match_parent" android:layout_height="200dp"
  61. motion:touchAnchorSide="bottom" motion:dragDirection="dragUp" /> <ConstraintSet android:id="@+id/start"> <Constraint android:id="@id/motionLayout" android:layout_width="match_parent" android:layout_height="200dp" motion:layout_constraintTop_toTopOf="parent"

    /> <Constraint android:id="@id/scrollable" android:layout_width="match_parent" android:layout_height="0dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintTop_toBottomOf="@+id/motionLayout" /> <Constraint android:id="@id/fab" android:layout_width="wrap_content"
  62. <Constraint android:id="@id/scrollable" android:layout_width="match_parent" android:layout_height="0dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintTop_toBottomOf="@+id/motionLayout" /> <Constraint android:id="@id/fab" android:layout_width="wrap_content"

    android:layout_height="wrap_content" android:visibility="invisible" motion:layout_constraintTop_toBottomOf="parent" motion:layout_constraintRight_toRightOf="parent" android:layout_marginTop="8dp" android:layout_marginRight="8dp"/> </ConstraintSet>
  63. <Constraint android:id="@id/scrollable" android:layout_width="match_parent" android:layout_height="0dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintTop_toBottomOf="@+id/motionLayout" /> <Constraint android:id="@id/fab" android:layout_width="wrap_content"

    android:layout_height="wrap_content" android:visibility="invisible" motion:layout_constraintTop_toBottomOf="parent" motion:layout_constraintRight_toRightOf="parent" android:layout_marginTop="8dp" android:layout_marginRight="8dp"/> </ConstraintSet>
  64. <Constraint android:id="@id/scrollable" android:layout_width="match_parent" android:layout_height="0dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintTop_toBottomOf="@+id/motionLayout" /> <Constraint android:id="@id/fab" android:layout_width="wrap_content"

    android:layout_height="wrap_content" android:visibility="invisible" motion:layout_constraintTop_toBottomOf="parent" motion:layout_constraintRight_toRightOf="parent" android:layout_marginTop="8dp" android:layout_marginRight="8dp"/> </ConstraintSet>
  65. <ConstraintSet android:id="@+id/end"> <Constraint android:id="@id/motionLayout" android:layout_width="match_parent" android:layout_height="56dp" motion:layout_constraintTop_toTopOf="parent" motion:progress="1" /> <Constraint

    android:id="@id/scrollable" android:layout_width="match_parent" android:layout_height="0dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintTop_toBottomOf="@+id/motionLayout" /> <Constraint android:id="@id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content"
  66. <Constraint android:id="@id/scrollable" android:layout_width="match_parent" android:layout_height="0dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintTop_toBottomOf="@+id/motionLayout" /> <Constraint android:id="@id/fab" android:layout_width="wrap_content"

    android:layout_height="wrap_content" android:visibility="visible" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintRight_toRightOf="parent" android:layout_marginBottom="8dp" android:layout_marginRight="8dp" /> </ConstraintSet> </Transition>
  67. <Constraint android:id="@id/scrollable" android:layout_width="match_parent" android:layout_height="0dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintTop_toBottomOf="@+id/motionLayout" /> <Constraint android:id="@id/fab" android:layout_width="wrap_content"

    android:layout_height="wrap_content" android:visibility="visible" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintRight_toRightOf="parent" android:layout_marginBottom="8dp" android:layout_marginRight="8dp" /> </ConstraintSet> </Transition>
  68. <Constraint android:id="@id/scrollable" android:layout_width="match_parent" android:layout_height="0dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintTop_toBottomOf="@+id/motionLayout" /> <Constraint android:id="@id/fab" android:layout_width="wrap_content"

    android:layout_height="wrap_content" android:visibility="visible" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintRight_toRightOf="parent" android:layout_marginBottom="8dp" android:layout_marginRight="8dp" /> </ConstraintSet> </Transition>
  69. { 360 | AnDev } 2018 Documentation ★ Online Documentation:

    https://developer.android.com/reference/android/ support/constraint/motion/package-summary ★ Medium Articles: ★ Introduction to MotionLayout - Part I : http://bit.ly/2O4AmIz ★ Introduction to MotionLayout - Part II : http://bit.ly/2uPuWbw ★ Introduction to MotionLayout - Part III : http://bit.ly/2zRjCSj ★ https://github.com/googlesamples/android-ConstraintLayoutExamples