MotionLayout은 ConstraintLayout의 서브클래스이며, 위젯 애니메이션과 모션을 관리할 수 있는 레이아웃 입니다.
기존에는 애니메이션을 정의하고 실행시키기 위해서는 보통 xml에서 정의한 후 코드로 실행시키는 방식이었지만, MotionLayout은 xml으로만 애니메이션을 정의 및 실행 시킬 수 있습니다.
MotionLayout의 특징은 애니메이션과 관련된 내용을 별도의 xml(MotionScene)에 분리하여 재사용한다 라는 점 입니다.
이번 포스트에서는 MotionLayout의 여러 태그에 대해 알아보도록 하겠습니다.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.motion.widget.MotionLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/motionLayout"
android:layout_width="match_parent"
app:layoutDescription="@xml/scene_5"
android:layout_height="match_parent"
tools:showPaths="true">
<View
android:id="@+id/view"
android:layout_width="64dp"
android:layout_height="64dp"/>
</androidx.constraintlayout.motion.widget.MotionLayout>
MotionLayout은 Constraint의 서브클래스이기 때문에 기존에 사용하던 ConstraintLayout에서 MotionLayout으로 태그만 바꿔주고 layoutDescription
에 참조하는 MotionScene을 지정해주면 동일하게 사용 가능합니다
MotionLayout이 참조하는 MotionScene은 내부에 ConstraintSet을 포함하고 있고, 이를 기반으로 레이아웃의 구조와 애니메이션을 구성합니다.
<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<Transition
app:constraintSetEnd="@id/end"
app:constraintSetStart="@id/start"
app:motionInterpolator="linear">
<OnSwipe
app:dragDirection="dragDown"
app:touchAnchorId="@id/button"
app:touchAnchorSide="bottom"/>
</Transition>
<ConstraintSet android:id="@+id/start">
<Constraint
android:id="@+id/button"
android:layout_width="30dp"
android:layout_height="30dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" >
<CustomAttribute
app:attributeName="backgroundColor"
app:customColorValue="@color/purple_200"/>
</Constraint>
</ConstraintSet>
<ConstraintSet android:id="@+id/end">
<Constraint
android:id="@+id/button"
android:layout_width="150dp"
android:layout_height="150dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" >
<CustomAttribute
app:attributeName="backgroundColor"
app:customColorValue="@color/purple_500"/>
</Constraint>
</ConstraintSet>
</MotionScene>
MotionScene은 res/xml에 저장됩니다.
MotionScene안에는 Transition
이 꼭 포함되어야 하며, 추가적으로 ConstraintSet
을 포함할 수 있습니다.
Transition
은 모션의 시작, 종료 상태와 duration 그리고 어떤 사용자 입력으로 트리거 되는지를 지정합니다.
constraintSetStart
: 모션의 시작 상태, ConstraintSet이나 layout을 참조합니다.constraintSetEnd
: 모션의 종료 상태, ConstrainSet이나 layout을 참조합니다.duration
: 모션의 지속 시간을 정의합니다.motionInterpolator
: 애니메이션 속도를 조절합니다. (linear, bounce 등)staggered
: 0부터 1사이의 float 값이 들어가며, 지정된 비율만큼 모션을 지연시킵니다.모션을 트리거 하는 방법에는 두 가지가 있습니다. OnSwipe
와 OnClick
입니다.
각 트리거마다 지정해야 하는 속성들은 다음과 같습니다.
dragDirection
: Swipe 방향을 지정합니다.touchAnchorId
: 추적할 view를 지정합니다.touchAnchorSide
: 추적할 view의 측면을 지정합니다.touchRegionId
: 터치 영역을 제한할 view를 지정합니다.targetId
: 모션을 트리거할 view를 지정합니다.clickAction
: start에서 end로 어떻게 모션을 진행시킬 지 지정합니다 (toggle, jumpToStart 등)MotionLayout은 start와 end를 지정해서 그 사이에 애니메이션 효과를 주는 것 입니다.
KeyFrameSet을 이용하면 start와 end 사이에 중간 상태를 만들 수 있습니다.
KeyPosition
,KeyAttribute
를 포함할 수 있습니다.
<KeyPosition
app:framePosition="60"
app:keyPositionType="parentRelative"
app:motionTarget="@id/view"
app:percentX="0.9" />
모션이 진행되는 중에, 특정 시점에 view의 위치를 지정합니다.
motionTarget
: 대상 view를 지정합니다.keyPositionType
: 위치를 무엇을 기준으로 잡을지 지정합니다 (parent, delta 등)percentX
: 지정한 기준으로부터 어느정도 X위치에 도달할지 지정합니다.percentY
: 지정한 기준으로부터 어느정도 Y위치에 도달할지 지정합니다.framePosition
: 전체 모션 중 어떤 시점에 위치할지 지정합니다 (0~100)<KeyAttribute
android:scaleX="1.3"
android:scaleY="1.3"
app:framePosition="50"
app:motionTarget="@id/view"/>
모션이 진행되는 중에, 특점 시점에 view의 attribute를 조작합니다.
지정할 수 있는 attribute는 애니메이션을 줄 수 있는 대부분의 attribute가 가능합니다.
motionTarget
: 대상 view를 지정합니다.framePosition
: 전체 모션 중 어떤 시점에 위치할지 지정합니다 (0~100)<ConstraintSet android:id="@+id/start">
<Constraint
android:id="@+id/button"
android:layout_width="30dp"
android:layout_height="30dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" >
<CustomAttribute
app:attributeName="backgroundColor"
app:customColorValue="@color/purple_200"/>
</Constraint>
</ConstraintSet>
<ConstraintSet android:id="@+id/end">
<Constraint
android:id="@+id/button"
android:layout_width="150dp"
android:layout_height="150dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" >
<CustomAttribute
app:attributeName="backgroundColor"
app:customColorValue="@color/purple_500"/>
</Constraint>
</ConstraintSet>
일반적으로 Transition
은 2개의 ConstraintSet
를 가리키는데, 하나는 모션의 시작을 정의하고 다른 하나는 끝을 정의합니다.
ConstraintSet
은 Constarint들을 가지며, 이를 통해 모션 시작 또는 종료 상태를 지정할 수 있습니다.
위 예시 코드는 button의 사이즈가 30x30dp에서 150x150dp로 커지면서 컬러가 변하는 ConstraintSet
입니다.
Constraint
에서는 ConstraintLayout에서 View를 작성하듯 작성하면 됩니다.
특정 속성을 변경할 때에는 CustomAttribute
를 이용합니다.
attributeName
: 속성을 지정합니다. test라고 지정하면 setTest 메소드를 찾아 변경합니다.custom~~~Value
: 속성의 타입을 지정합니다.https://developer.android.com/training/constraint-layout/motionlayout/examples