0. 소개

 

MotionLayout은 ConstraintLayout 안에 있는 객체들에 대해서 XML 파일들만 추가해서 간단하게 레이아웃 애니메이션 효과를 줄 수 있는 툴 정도로 이해하면 될 것 같다. 예제로 구글 소개글에 있는 예제들 봐도 되고 아래 gif 이미지를 참고해도 좋다. 2018년 말에 나온 기능인데 이제 와서 글을 쓰고 있으니 아주 뒷북인 감이 없지 않다.

 

스와이프로 빨간 사각형을 움직이는 애니메이션을 줄 수 있다.

1. 원리

 

MotionLayout 은 완전히 새로운 기능으로 도입 된 것은 아니고 원래 ConstraintLayout에서 애니메이션 효과를 주기 위해 사용한 ConstraintSet + TransitionManager를 좀 더 쉽게 사용할 수 있는 툴로 도입 됐다. ConstarintSet + TransitionManager에 대해 생소하신 분들은 이 유튜브 영상을 참고하자. 기존 효과보다 더 좋아진 점은 ConstraintSet + TransitionManager 조합에서는 간단한 효과의 경우에도 액티비티, 프래그먼트단에서 코드를 추가해야 했는데 MotionLayout을 사용하면 XML 코드단에서만 수정하면 돼서 변경의 범위를 최소화 할 수 있는 것 같다.

 

ConstarintLayout의 확장 기능으로 도입된 만큼 MotionLayout은 ConstraintLayout의 일부 요소들을 상속 받고 있다. 아래 그림에서 MotionLayout 의 기본 요소인 MotionScene이 ConstraintSet의 속성들을 포함하고 있는 것을 볼 수 있다. 실제 코드에서는 이 요소를 활용해 ConstraintLayout 내부의 객체들의 효과를 주는 일을 한다. 그 아래 Transition 속성을 보면 OnClick과 OnSwipe가 있는데 이는 클릭과 스와이프 인터랙션에 대해서 콜백을 줄 수 있는 것으로 이해하면 된다. 이 글에서는 MotionLayout은 ConstraintLayout 의 속성들을 이용해 애니메이션 할 수 있다는 점이란 것을 기억하고 자세한 내용은 개발 문서를 참고하도록 하자. 

 

2. 예제

 

MotionLayout을 사용하려면 우선 라이브러리를 추가해야한다. build.gradle에 아래의 코드를 추가해 최신 ConstraintLayout 소스를 불러오자. 번외로 2018년도 즈음에 MotionLayout이 ConstraintLayout 2.0.0 라이브러리에 포함되기 시작했는데 아직도 beta 버전에 머무르고 있는거 보니 다른 feature들과 같이 정식으로 릴리즈 되려는 모양인가보다.

 

implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta4'

 

정상적으로 라이브러리를 불러 왔다면 이제 레이아웃 파일을 수정할 때다. 아래 코드는 기존에 있던 xml 파일을 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:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layoutDescription="@anim/motion_scene"
    tools:context=".MainActivity">
    <View
        android:id="@+id/button"
        android:layout_width="64dp"
        android:layout_height="64dp"
        android:background="@color/colorAccent"
        android:text="Button"/>
</androidx.constraintlayout.motion.widget.MotionLayout>

 

원래는 ConstraintLayout을 사용했었는데 MotionLayout을 사용하고자 클래스 이름을 MotionLayout으로 변경했다. MotionLayout이 ConstraintLayout을 상속받은 클래스이기 때문에 자식 뷰에서 특별히 바꿔야할 것은 없다. 새롭게 추가한 코드는 app:layoutDescription인데 여기에 Motion 효과를 명시한 xml 파일을 넣었다. 

 

motion_scene 파일은 다음과 같다.

 

<?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">
        <OnSwipe
            motion:touchAnchorId="@+id/button"
            motion:touchAnchorSide="right"
            motion:dragDirection="dragRight" />
    </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"
            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>

Transition 속성을 보면 motion:constraintSetStart와 motion:constraintSetEnd 속성이 있는데 이는 애니메이션 효과 동안 constraint의 시작과 끝에 대한 정보를 나타낸다. 아래 코드 보면 두개의 ConstraintSet이 있는 것을 볼 수 있는데 시작할 때의 값과 끝의 값이 다른 것을 알 수 있다. 이 포스트 상단에 있는 gif 파일과 일치하는 것을 볼 수 있다.

 

그 아래 OnSwipe는 특정 뷰를 스와이프 할 때 줄 수 있는 효과를 명시했다. touchAnchorId의 값이 +@id/button으로 설정돼있는데 이는 MotionLayout에서 button 이란 id를 가진 뷰에게는 swipe 효과를 줄 것이라는 뜻이다. motion:touchAnchorSide와 motion:dragDirection이 있는데 이 값들을 이용해서 스와이프에 추가로 효과를 줄 수 있다.

 

3. 짧은 평

 

Android Studio 4.0에서는 XML파일에 MotionLayout 미리보기 화면에서도 애니메이션 효과를 보여줄 예정이라고 하니(4.0-beta 버전 참고) 구글에서도 MotionLayout을 사용하는 것을 적극 권장하는 것 같다. 앞으로 MotionLayout에서 추가된 기능이 나올 것 같으니 지금부터 프로젝트에 도입하는 것을 목표로 해야겠다.