밍맹의 생각날 때 적는 블로그

[Android/Kotlin] MotionLayout (애니메이션을 쉽게 적용하기) 본문

안드로이드

[Android/Kotlin] MotionLayout (애니메이션을 쉽게 적용하기)

mingmaeng 2020. 9. 6. 22:20

 

안드로이드 앱을 만들 때마다 항상 하는 고민이 있습니다.

어떻게 해야 앱을 멋있게 만들 수 있을까....

UI/UX에 맞게 앱을 만드는 것도 멋있지만 거기에 애니메이션이 추가가 된다면 얼마나 멋있을까요?

다음 웹툰만 보더라도 애니메이션을 넣어서 엄청 예쁘게 보이게 됩니다.

유튜브나 유튜브 뮤직에서 보이는 슬라이드 애니메이션을 생각하시면 될 것 같네요. ㅎㅎ

 

이를 만족시키기 위해 여기저기 돌아다니던 중 MotionLayout을 알게 되었습니다.

 

그럼 MotionLayout이 뭔지 한 번 확인해 보도록 하겠습니다.

 

해당 포스팅은 Android Developer에 있는 내용을 중심으로 작성하였습니다.

 

developer.android.com/training/constraint-layout/motionlayout?hl=ko

 

MotionLayout으로 모션 및 위젯 애니메이션 관리  |  Android 개발자  |  Android Developers

MotionLayout은 앱에서 모션과 위젯 애니메이션을 관리하는 데 사용할 수 있는 레이아웃 유형입니다. MotionLayout은 ConstraintLayout의 서브클래스이며 ConstraintLayout의 다양한 레이아웃 기능을 기초로 합��

developer.android.com

 

 

MotionLayout이란?

간단하게 MotionLayout을 살펴보겠습니다.

 

  • ConstraintLayout 2.0부터 추가
  • 2018년 Google I/O에서 소개
  • ConstraintLayout의 서브 클래스 ( ConstraintLayout 처럼 사용 가능)
  • 애니메이션에 중점을 둔 새로운 ViewGroup
  • MotionScenes이라는 xml을 사용하여 작성
  • API 14 부터 호환

2018년에 출시한 MotionLayout은 지금까지도 계속 발전해가고 있습니다.

그러다가 이번에 안드로이드 스튜디오가 4.0으로 업데이트 되고 나서부터 Motion Editor를 사용할 수 있게 됩니다.

Motion Editor의 등장으로 인해 우리는 xml 코드 작성이 아닌 GUI적으로 모션작업을 할 수 있게 되었습니다!!!

또한 에뮬레이터를 일일이 구동할 필요 없이 바로 미리보기 창에서 재생해 볼 수 있습니다. ㅎㅎ

 

- 결론 -

안드로이드 스튜디오 4.0 이후로 MotionLayout 애니메이션을 시각적으로 쉽게 디자인 할 수 있다.

일일히 실행해서 확인할 필요가 없다.

 

 

Layout설정

레이아웃은 MotionLayout을 사용하게 됩니다.

MotionLayout은 ConstraintLayout을 상속받은 ViewGroup이기 때문에 xml 작성은 기존에 사용하던

ConstraintLayout과 동일하게 작성해주면 됩니다.

 

    <?xml version="1.0" encoding="utf-8"?>
    <!-- activity_main.xml -->
    <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"
        android:layout_height="match_parent"
        app:layoutDescription="@xml/scene_01"
        tools:showPaths="true">

        <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과 다른 점은 app:layoutDescription 속성을 추가해줘야 한다는 것입니다.

이 속성은 해당 xml에 MotionScene을 참조시켜 애니메이션을 제어하는 속성입니다.

 

MotionScene은 상응하는 레이아웃에 모든 모션 설명을 포함하는 XML 리소스 파일입니다.

즉, 참조되는 레이아웃에 모든 애니메이션을 설정하고 제어하는 XML 파일입니다.

MotionLayout을 사용할 때 애니메이션에 관련한 작업은 모두 MotionScene에서 작업합니다.

 

 

scene_01.xml

    <?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>
        

 

MotionScene은 <MotionScene>태그로 둘러싸여 있습니다.

주요 태그를 살펴보면 다음과 같습니다.

 

  • <Transition>
    모션의 기본 정의를 포함하는 태그. 시작과 종료를 설정하고 애니메이션 시간을 정할 수 있습니다.
  • <OnSwipe>
    터치 모션을 제어할 수 있습니다. Swipe 또는 Click으로 애니메이션을 실행 시키고 제어할 수 있습니다.
  • <ConstraintSet>
    모션에 대한 제약조건을 설정하는 태그입니다.
    id 값을 통해 <Transition>태그 에서 시작과 종료지점을 나타낼 수 있습니다.
    <ConstraintSet>태그 안에서 <Constraint> 태그를 통해 뷰 들의 위치를 정해줄 수 있습니다.
  • <Constraint>
    MotionLayout에 작성된 뷰들의 위치를 설정할 수 있습니다.
  • <CustomAttribute>
    뷰의 위치 또는 속성의 전환을 설정해 줄 수 있습니다.
    `motion:attributeName` 속성은 필수로 선언해야 하며, getter와 setter가 있는 객체와 일치해야 합니다.
    개발자 문서의 예시처럼 `BackgroundColor`속성은 `getBackgroundColor()`와 `setBackgroundColor()` 메서드가
    존재하기 때문에 사용 가능합니다.
    <Constraint
        android:id="@+id/button" ...>
        <CustomAttribute
            motion:attributeName="backgroundColor"
            motion:customColorValue="#D81B60"/>
    </Constraint>
    

<CustomAttribute>에 선언할 다른 속성은 값 유형을 기반으로 합니다. 지원되는 유형은 다음과 같습니다.

 

  • motion:customColorValue - 색상
  • motion:customIntegerValue - 정수
  • motion:customFloatValue - 부동수
  • motion:customStringValue - 문자열
  • motion:customDimension - 측정기준
  • motion:customBoolean - 부울

 

예시로 사용된 배경색이 변경되는 애니메이션 입니다.

 

    <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">
            <CustomAttribute
                motion:attributeName="backgroundColor"
                motion:customColorValue="#D81B60" />
        </Constraint>
    </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">
            <CustomAttribute
                motion:attributeName="backgroundColor"
                motion:customColorValue="#9999FF" />
        </Constraint>
    </ConstraintSet>
    

 

 

중간 중간 애니메이션 넣기 KeyFrame

영상 편집을 해보신 경험이 있나요? 영상에 효과를 주거나 자막을 넣을 때 키프레임등을 통해 적절한 타이밍에

다양한 효과를 줄 수 있습니다. MotionScene에서도 이와 같은 효과를 낼 수 있는데, 바로 KeyFrame을 이용하면

됩니다.

 

    <KeyFrameSet>
        [ <KeyPosition/>... ]
        [ <KeyAttribute/>...]
    </KeyFrameSet>
    

 

<KeyFrameSet> 태그 안에<KeyPosition>, <KeyAttribute>태그를 포함 시켜 애니메이션 중간중간에 키프레임을

설정할 수 있습니다. 태그 속성은 다음과 같습니다.

 

    <KeyPosition
        motion:motionTarget="@id/targetPath"
        motion:framePosition="percentage"
        motion:keyPositionType="type"
        motion:percentX="xOffset"
      motion:percentY="yOffset"
    />
    

 

<KeyPosition>

  • 특정 시점에서 뷰의 위치를 변경시킵니다.
  • motionTarget : 타겟되는 뷰를 나타냅니다.
  • framePosition : 애니메이션의 시작과 끝을 0 ~ 100이라 했을 때, 1~99까지의 위치를 나타냅니다.
    예를 들어 25라면 애니메이션 경로의 1/4 지점이 됩니다.
  • percentX/Y : 뷰가 도달하는 위치를 지정합니다. keyPositionType에 따라 거리 계산 방식이 달라집니다.
  • curvFit : 직선/곡선 이동 여부를 설정합니다.
  • keyPositionType : 뷰가 도달하는 위치를 계산하는 방식입니다.

motion:keyPositionType

parentRelative

부모를 기준으로 계산합니다. 예를 들어 percentY가 0.25라고 가정할 경우

부모 레이아웃의 높이를 기준으로 0.25 위치까지 이동하는 것을 뜻합니다.

 

deltaRelative

시작과 끝의 좌표를 계산해 그 이동 경로를 백분율로 나타냅니다.

percentY가 0.25일 경우 이동 경로 Y축의 0.25만큼 이동합니다.

 

pathRelative

시작과 끝의 좌표를 일직선상으로 놓고, 이를 x축으로 둡니다.

percentY가 0.25일 경우 위의 그림처럼 시작과 끝의 좌표를 계산해 그 거리를 백분율로 나타냅니다.

그리고 해당 경로를 x축으로한 상태로 y축을 새로 계산합니다.

이 때 계산한 y축의 0.25만큼 위치가 이동합니다.

 

 

<KeyAttribute>

<KeyAttribute>태그는 <CustomAttribute>와 비슷한 역할을 합니다.

해당 키프레임에서 뷰의 속성을 지정할 수 있습니다.

 

    <KeyAttribute
      motion:motionTarget="@id/targetPath"
      motion:framePosition="percentage"
      [ attribute = value ]
    />
    

 

변경할 수 있는 속성은 다음과 같습니다. 우리가 애니메이션 적용에서 알고 있는 속성들을 거의 다 쓸 수 있다고

생각하시면 편합니다.

 

  • visibility
  • alpha
  • elevation
  • rotation
  • scale
  • translation

이번 포스팅은 MotionLayout에 대한 개념에 대해서 제가 구글개발 문서를 보고 공부한 내용을 적어보았습니다.

이를 토대로 실습한 내용도 포스팅하려고 했는데 글이 길어져서 다음 포스팅으로 옮기도록 하겠습니다.

MotionLayout이 새로 생김으로 인해서 애니메이션을 적용하는데 훨씬 더 편하게 적용할 수 있게 됐네요 ㅎㅎ

 

Android Studio 4.0에서 새로 지원해주는 Motion Editor를 이용해 애니메이션을 적용하는 실습을

다음 포스팅에 작성하겠습니다 ㅎㅎ

Comments