Motion Layout

Motion Layout

Apresentada na trilha Android o TDC São Paulo 2019

2dc2a52d38ee8c184deeceaadf9ed6ba?s=128

Rafael Toledo

July 17, 2019
Tweet

Transcript

  1. Motion Layout Rafael Toledo @_rafaeltoledo

  2. Mas não era ConstraintLayout até ontem???

  3. Mas não era ConstraintLayout até ontem???

  4. KEEP CALM AND LET'S RECAP Layouts no Android

  5. ConstraintLayout 1.x Resolve o problema da hierarquia de views

  6. ConstraintLayout 1.x Resolve o problema da hierarquia de views Flexibilidade

    para layouts complexos
  7. ConstraintLayout 1.x Resolve o problema da hierarquia de views Flexibilidade

    para layouts complexos Amigável ao editor visual
  8. ConstraintLayout 1.x Resolve o problema da hierarquia de views Flexibilidade

    para layouts complexos Amigável ao editor visual
  9. ConstraintLayout 1.x Resolve o problema da hierarquia de views Flexibilidade

    para layouts complexos Amigável ao editor visual Várias outras coisas que eram treta de se fazer antes (Barrier, Guideline, Chains, layout circular, etc)
  10. e

  11. E

  12. ConstraintLayout 1.x Resolve o problema da hierarquia de views Flexibilidade

    para layouts complexos Amigável ao editor visual Várias outras coisas que eram treta de se fazer antes (Barrier, Guideline, Chains, layout circular, etc) Um jeito simples de animar estados de uma tela (ConstraintSets)
  13. <androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/root"> <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent"

    /> </androidx.constraintlayout.widget.ConstraintLayout>
  14. <androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/root"> <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent"

    /> </androidx.constraintlayout.widget.ConstraintLayout>
  15. <androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/root"> <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent"

    /> </androidx.constraintlayout.widget.ConstraintLayout>
  16. <androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/root"> <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent"

    /> </androidx.constraintlayout.widget.ConstraintLayout>
  17. <androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/root"> <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent"

    /> </androidx.constraintlayout.widget.ConstraintLayout>
  18. <androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/root"> <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent"

    /> </androidx.constraintlayout.widget.ConstraintLayout>
  19. None
  20. root.setOnClickListener { ConstraintSet().apply { constrainWidth(text, WRAP_CONTENT) constrainHeight(text, WRAP_CONTENT) connect(text, END,

    PARENT_ID, END) connect(text, TOP, PARENT_ID, TOP) applyTo(root) } }
  21. None
  22. None
  23. root.setOnClickListener { ConstraintSet().apply { constrainWidth(text, WRAP_CONTENT) constrainHeight(text, WRAP_CONTENT) connect(text, END,

    PARENT_ID, END) connect(text, TOP, PARENT_ID, TOP) applyTo(root) } }
  24. root.setOnClickListener { TransitionManager.beginDelayedTransition(root) ConstraintSet().apply { constrainWidth(text, WRAP_CONTENT) constrainHeight(text, WRAP_CONTENT) connect(text,

    END, PARENT_ID, END) connect(text, TOP, PARENT_ID, TOP) applyTo(root) } }
  25. root.setOnClickListener { TransitionManager.beginDelayedTransition(root) ConstraintSet().apply { constrainWidth(text, WRAP_CONTENT) constrainHeight(text, WRAP_CONTENT) connect(text,

    END, PARENT_ID, END) connect(text, TOP, PARENT_ID, TOP) applyTo(root) } }
  26. root.setOnClickListener { TransitionManager.beginDelayedTransition(root) ConstraintSet().apply { constrainWidth(text, WRAP_CONTENT) constrainHeight(text, WRAP_CONTENT) connect(text,

    END, PARENT_ID, END) connect(text, TOP, PARENT_ID, TOP) applyTo(root) } } implementation 'androidx.transition:transition:1.1.0'
  27. None
  28. root.setOnClickListener { TransitionManager.beginDelayedTransition(root) ConstraintSet().apply { load(R.id.dest) applyTo(root) } }

  29. ConstraintLayout 2.0

  30. MotionLayout

  31. MotionLayout Estende ConstraintLayout Adiciona uma série de funcionalidades para controle

    de animação
  32. <androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/root"> <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent"

    /> </androidx.constraintlayout.widget.ConstraintLayout>
  33. <androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/root"> <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent"

    /> </androidx.constraintlayout.widget.ConstraintLayout>
  34. <androidx.constraintlayout.motion.widget.MotionLayout android:id="@+id/root" app:layoutDescription="@xml/motion_scene"> <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" app:layout_constraintBottom_toBottomOf="parent"

    app:layout_constraintStart_toStartOf="parent" /> </androidx.constraintlayout.motion.widget.MotionLayout>
  35. <androidx.constraintlayout.motion.widget.MotionLayout android:id="@+id/root" app:layoutDescription="@xml/motion_scene"> <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" app:layout_constraintBottom_toBottomOf="parent"

    app:layout_constraintStart_toStartOf="parent" /> </androidx.constraintlayout.motion.widget.MotionLayout>
  36. <MotionScene> <ConstraintSet android:id="@+id/start"> <Constraint android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" />

    </ConstraintSet> </MotionScene>
  37. <MotionScene> <ConstraintSet android:id="@+id/start"> <Constraint android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" />

    </ConstraintSet> <ConstraintSet android:id="@+id/end"> <Constraint android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" /> </ConstraintSet> </MotionScene>
  38. <MotionScene> <ConstraintSet android:id="@+id/start"> <Constraint android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" />

    </ConstraintSet> <ConstraintSet android:id="@+id/end"> <Constraint android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" /> </ConstraintSet> </MotionScene>
  39. <MotionScene> <ConstraintSet android:id="@+id/start"> <Constraint android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" />

    </ConstraintSet> <ConstraintSet android:id="@+id/end"> <Constraint android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" /> </ConstraintSet> </MotionScene>
  40. <MotionScene> <ConstraintSet android:id="@+id/start"> <Constraint android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" />

    </ConstraintSet> <ConstraintSet android:id="@+id/end"> <Constraint android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" /> </ConstraintSet> </MotionScene>
  41. <MotionScene> <ConstraintSet android:id="@+id/start"> <Constraint android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" />

    </ConstraintSet> <ConstraintSet android:id="@+id/end"> <Constraint android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" /> </ConstraintSet> </MotionScene>
  42. <MotionScene> <ConstraintSet android:id="@+id/start"> <Constraint android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" />

    </ConstraintSet> <ConstraintSet android:id="@+id/end"> <Constraint android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" /> </ConstraintSet> </MotionScene>
  43. <MotionScene> <ConstraintSet android:id="@+id/start"> <Constraint android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" />

    </ConstraintSet> <ConstraintSet android:id="@+id/end"> <Constraint android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" /> </ConstraintSet> </MotionScene>
  44. <MotionScene> <ConstraintSet android:id="@+id/start"> ... </ConstraintSet> <ConstraintSet android:id="@+id/end"> ... </ConstraintSet> </MotionScene>

  45. <MotionScene> <Transition app:constraintSetEnd="@+id/end" app:constraintSetStart="@+id/start" /> <ConstraintSet android:id="@+id/start"> ... </ConstraintSet> <ConstraintSet

    android:id="@+id/end"> ... </ConstraintSet> </MotionScene>
  46. <MotionScene> <Transition app:constraintSetEnd="@+id/end" app:constraintSetStart="@+id/start" /> <ConstraintSet android:id="@+id/start"> ... </ConstraintSet> <ConstraintSet

    android:id="@+id/end"> ... </ConstraintSet> </MotionScene>
  47. <MotionScene> <Transition app:constraintSetEnd="@+id/end" app:constraintSetStart="@+id/start"> <OnClick app:clickAction="toggle" app:targetId="@+id/root" /> </Transition> <ConstraintSet

    android:id="@+id/start"> ... </ConstraintSet> <ConstraintSet android:id="@+id/end"> ... </ConstraintSet> </MotionScene>
  48. <MotionScene> <Transition app:constraintSetEnd="@+id/end" app:constraintSetStart="@+id/start"> <OnClick app:clickAction="toggle" app:targetId="@+id/root" /> </Transition> <ConstraintSet

    android:id="@+id/start"> ... </ConstraintSet> <ConstraintSet android:id="@+id/end"> ... </ConstraintSet> </MotionScene> toggle jumpToEnd jumpToStart transitionToEnd transitionToStart
  49. None
  50. class MainActivity : AppCompatActivity(R.layout.activity_main)

  51. class MainActivity : AppCompatActivity(R.layout.activity_main)

  52. class MainActivity : AppCompatActivity(R.layout.activity_main) implementation 'androidx.appcompat:appcompat:1.1.0-rc01'

  53. class MainActivity : AppCompatActivity(R.layout.activity_main) implementation 'androidx.appcompat:appcompat:1.1.0-rc01'

  54. Voltando...

  55. ConstraintSets

  56. Atributos do ConstraintSet Layout - atributos de posicionamento

  57. Atributos do ConstraintSet Layout Transform - rotação, redefinição de tamanho,

    translação
  58. Atributos do ConstraintSet Layout Transform Property - transparência (alpha), visibilidade

  59. Atributos do ConstraintSet Layout Transform Property Motion - caminho (path),

    easing (timing de movimento)
  60. Atributos do ConstraintSet Layout Transform Property Motion CustomAttribute - qualquer

    atributo da View, via reflection
  61. <MotionScene> ... <ConstraintSet android:id="@+id/start"> <Constraint android:id="@+id/text"> <Layout android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent"

    app:layout_constraintStart_toStartOf="parent" /> </Constraint> </ConstraintSet> <ConstraintSet android:id="@+id/end"> ... </ConstraintSet> </MotionScene>
  62. <MotionScene> ... <ConstraintSet android:id="@+id/start"> <Constraint android:id="@+id/text"> <Layout android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent"

    app:layout_constraintStart_toStartOf="parent" /> </Constraint> </ConstraintSet> <ConstraintSet android:id="@+id/end"> ... </ConstraintSet> </MotionScene>
  63. <MotionScene> ... <ConstraintSet android:id="@+id/start"> <Constraint android:id="@+id/text"> <Layout android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent"

    app:layout_constraintStart_toStartOf="parent" /> </Constraint> </ConstraintSet> <ConstraintSet android:id="@+id/end"> ... </ConstraintSet> </MotionScene>
  64. <MotionScene> ... <ConstraintSet android:id="@+id/start"> <Constraint android:id="@+id/text"> <Layout android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent"

    app:layout_constraintStart_toStartOf="parent" /> <Motion app:pathMotionArc="startHorizontal" /> </Constraint> </ConstraintSet> <ConstraintSet android:id="@+id/end"> ... </ConstraintSet> </MotionScene>
  65. <MotionScene> ... <ConstraintSet android:id="@+id/start"> <Constraint android:id="@+id/text"> <Layout android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent"

    app:layout_constraintStart_toStartOf="parent" /> <Motion app:pathMotionArc="startHorizontal" /> </Constraint> </ConstraintSet> <ConstraintSet android:id="@+id/end"> ... </ConstraintSet> </MotionScene>
  66. None
  67. class MainActivity : AppCompatActivity(R.layout.activity_main) e a Activity...

  68. <MotionScene> <Transition app:constraintSetEnd="@+id/end" app:constraintSetStart="@+id/start" app:duration="400" app:motionInterpolator="easeIn"> <OnClick app:clickAction="toggle" app:targetId="@+id/root" />

    </Transition> <ConstraintSet android:id="@+id/start" ... /> <ConstraintSet android:id="@+id/end" ... /> </MotionScene>
  69. <MotionScene> <Transition app:constraintSetEnd="@+id/end" app:constraintSetStart="@+id/start" app:duration="400" app:motionInterpolator="easeIn"> <OnClick app:clickAction="toggle" app:targetId="@+id/root" />

    </Transition> <ConstraintSet android:id="@+id/start" ... /> <ConstraintSet android:id="@+id/end" ... /> </MotionScene>
  70. <MotionScene> <Transition app:constraintSetEnd="@+id/end" app:constraintSetStart="@+id/start" app:duration="400" app:motionInterpolator="easeIn"> <OnClick app:clickAction="toggle" app:targetId="@+id/root" />

    </Transition> <ConstraintSet android:id="@+id/start" ... /> <ConstraintSet android:id="@+id/end" ... /> </MotionScene>
  71. <MotionScene> <Transition app:constraintSetEnd="@+id/end" app:constraintSetStart="@+id/start" app:duration="400" app:motionInterpolator="easeIn"> <OnClick app:clickAction="toggle" app:targetId="@+id/root" />

    </Transition> <ConstraintSet android:id="@+id/start" ... /> <ConstraintSet android:id="@+id/end" ... /> </MotionScene> anticipate bounce easeIn easeOut linear
  72. KeyFrameSet

  73. Início progresso: 0 Fim progresso: 100

  74. Início progresso: 0 Fim progresso: 100 KeyFrame progresso: 50

  75. Início progresso: 0 Fim progresso: 100 KeyFrame progr: 30 KeyFrame

    progr: 70
  76. KeyFrames KeyPosition - controla a posição durante a animação

  77. KeyFrames KeyPosition KeyAttribute - controla atributos da view durante a

    animação
  78. KeyFrames KeyPosition KeyAttribute KeyCicle - controla oscilações referentes ao posicionamento

    da view durante a animação
  79. KeyFrames KeyPosition KeyAttribute KeyCicle KeyTimeCicle - controla oscilações referentes ao

    tempo durante a animação
  80. <MotionScene> <Transition> <KeyFrameSet> <KeyPosition app:framePosition="50" app:keyPositionType="parentRelative" app:motionTarget="@+id/text" app:percentX=".5" app:percentY=".5" />

    </KeyFrameSet> <OnClick ... /> </Transition> ... </MotionScene>
  81. <MotionScene> <Transition> <KeyFrameSet> <KeyPosition app:framePosition="50" app:keyPositionType="parentRelative" app:motionTarget="@+id/text" app:percentX=".5" app:percentY=".5" />

    </KeyFrameSet> <OnClick ... /> </Transition> ... </MotionScene>
  82. <MotionScene> <Transition> <KeyFrameSet> <KeyPosition app:framePosition="50" app:keyPositionType="parentRelative" app:motionTarget="@+id/text" app:percentX=".5" app:percentY=".5" />

    </KeyFrameSet> <OnClick ... /> </Transition> ... </MotionScene>
  83. <MotionScene> <Transition> <KeyFrameSet> <KeyPosition app:framePosition="50" app:keyPositionType="parentRelative" app:motionTarget="@+id/text" app:percentX=".5" app:percentY=".5" />

    </KeyFrameSet> <OnClick ... /> </Transition> ... </MotionScene>
  84. <MotionScene> <Transition> <KeyFrameSet> <KeyPosition app:framePosition="50" app:keyPositionType="parentRelative" app:motionTarget="@+id/text" app:percentX=".5" app:percentY=".5" />

    </KeyFrameSet> <OnClick ... /> </Transition> ... </MotionScene>
  85. <MotionScene> <Transition> <KeyFrameSet> <KeyPosition app:framePosition="50" app:keyPositionType="parentRelative" app:motionTarget="@+id/text" app:percentX=".5" app:percentY=".5" />

    </KeyFrameSet> <OnClick ... /> </Transition> ... </MotionScene>
  86. <MotionScene> <Transition> <KeyFrameSet> <KeyPosition app:framePosition="50" app:keyPositionType="parentRelative" app:motionTarget="@+id/text" app:percentX=".5" app:percentY=".5" />

    </KeyFrameSet> <OnClick ... /> </Transition> ... </MotionScene>
  87. None
  88. None
  89. Dica Top!

  90. Dica FausTOP!

  91. <androidx.constraintlayout.motion.widget.MotionLayout android:id="@+id/root" app:layoutDescription="@xml/motion_scene" app:motionDebug="SHOW_ALL"> <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!"

    app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" /> </androidx.constraintlayout.motion.widget.MotionLayout> NO_DEBUG SHOW_PATH SHOW_PROGRESS SHOW_ALL
  92. None
  93. None
  94. E as tretas? Ainda está em beta - o lançamento

    de releases não é lá tão frequente "Às vezes" é tentativa e erro É fácil encontrar experimentos, difícil encontrar material pra começar
  95. Num futuro, teremos o Motion Editor!

  96. Links! Github com vários exemplos github.com/googlesamples/android-ConstraintLayoutExamples What's new in Constraint

    Layout (Google I/O 2019) youtube.com/watch?v=29gLA90m6Gk
  97. Outras talks! Advanced and Practical MotionLayout speakerdeck.com/kaeawc/advanced-and-practical-motionlayout MotionLayout: Make Your

    Apps Move Auto-magically speakerdeck.com/hashlin/motion-layout-make-your-apps-move-auto-magically Make Your App Dance with MotionLayout speakerdeck.com/brittbarak/make-your-app-dance-with-motionlayout
  98. Valeu! Rafael Toledo @_rafaeltoledo speakerdeck.com/rafaeltoledo