봄날은 갔다. 이제 그 정신으로 공부하자

MotionLayout - overview 본문

학습

MotionLayout - overview

길재의 그 정신으로 공부하자 2020. 11. 25. 19:37

안드로이드 앱 개발 시 버튼 위치가 변경되거나 스크롤에 따라 Toolbar 영역이 변하는 등의 처리는 해당 기능을 지원하는 라이브러리를 사용하거나, Animation 효과를 이용해서 직접 구현해 개발해왔습니다. 직접 구현하는 경우, 코드에 비지니스 로직 처리가 아닌 Animation 처리 코드가 다수 추가되다 보니 코드 복잡도를 증가시키는 문제가 있었습니다. 

2018년 구글에서 Animation 처리를 코드가 아닌 xml 레벨에서 처릴 할 수 있는 MotionLayout 툴을 발표했습니다.

이 글에서는 MotionLayout에서 제공하는 기능과 속성들에 대해 설명합니다.

 

* 이 글의 모든 설명 및 코드는 androidX를 사용 중인 것을 전제로 설명합니다.

 

MotionLayout이란?

MotionLayout은 앱에서 모션과 위젯 애니메이션을 관리하는 데 사용할 수 있는 레이아웃 유형입니다.

MotionLayout은 ConstraintLayout의 서브클래스이며 ConstraintLayout의 다양한 레이아웃 기능을 기초로 합니다.

MotionLayout은 레이아웃 전환과 복잡한 모션 처리 사이를 연결하며 레이아웃 전환 외에도 레이아웃 속성을 애니메이션으로 보여 줄 수 있습니다. 

또한 터치 입력과 같은 일부 조건에 따라 전환 내의 포인트를 즉시 표시할 수 있습니다.

* MotionLayout은 직접 하위 요소만 호환됩니다. 중첩 레이아웃 계층 구조 또는 Activity 전환은 지원하지 않습니다.

* 디자인 고려 사항

     MotionLayout 은 버튼 및 제목 표시줄과 같이 사용자가 상호작용하는 UI 요소의 이동, 크기 조절 및 애니메이션에

     사용합니다.

     앱의 모션을 어플리케이션의 불필요한 특수 효과에 사용하는 것을 추천하지 않습니다.

 

Getting Started

앱에서 MotionLayout을 사용하려면 아래 순서에 따라 MotionLayout 종속성 및 관련 코드를 추가해야 합니다.

 

Step 1. ConstraintLayout 종속항목 추가

ConstraintLayout 2.0 종속성을 앱의 build.gradle에 추가합니다.

dependencies {
    implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta1'
}

 

Step 2. MotionLayout 파일 만들기

위에 언급했듯이 MotionLayout은 ConstraintLayout의 서브클래스이므로 아래 예에서와 같이 레이아웃 리소스 파일에서 클래스 이름을 바꿔 기존 ConstraintLayout을 MotionLayout으로 전환할 수 있습니다.

<!-- before: ConstraintLayout -->
<androidx.constraintlayout.widget.ConstraintLayout .../>
 
<!-- after: MotionLayout -->
<androidx.constraintlayout.motion.widget.MotionLayout .../>

이렇게 전환한 MotionLayout은 아래 예시와 같이 기존 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>

 

Step 3. MotionScene 만들기

위 MotionLayout 예를 보면 기존 ConstraintLayout과는 다른 항목(app:layoutDescription) 을 확인할 수 있는데

이 app:layoutDescription 속성은 MotionScene을 참조합니다. MotionScene은 상응하는 레이아웃의 모든 모션 설명을 포함하는 XML 리소스 파일입니다. 레이아웃 정보를 모션 설명과 별도로 유지하기 위해 각 MotionLayout에서 개별 MotionScene을 참조합니다.

아래 MotionScene 코드는 위 코드의 기본 가로 모션을 수행하는 MotionScene 파일입니다.

<?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: 모션의 엔드포인트 참조이며 세부 내용은 <ConstraintSet> 요소에 정의됩니다.

    • motion:constraintSetEnd: 모션의 엔드포인트 참조이며 세부 내용은 <ConstraintSet> 요소에 정의됩니다.

    • motion:duration: 모션이 완료되는 데까지 걸리는 시간(단위: ms)입니다.

  • <OnSwipe>: 터치를 통해 모션을 제어할 수 있습니다.

    • motion:touchAnchorId: 스와이프하고 드래그할 수 있는 뷰를 나타냅니다.

    • motion:touchAnchorSide: 드래그되는 뷰의 측면을 정의합니다.

    • motion:dragDirection: 드래그 진행 방향을 나타냅니다.

  • <ConstraintSet>: 모션을 설명하는 다양한 조건을 정의합니다.

자세한 구성 요소에 대해서는 다음 글인 "MotionLayout - xml 구성요소"에서 자세히 설명합니다.

 

Interpolated attributes

MotionScene 파일에서 ConstraintSet 요소에는 전환하는 동안 아래와 같은 속성이 추가로 포함될 수 있습니다.

  • alpha

  • visibility

  • elevation

  • rotation, rotationX, rotationY

  • translationZ, translationY, translationX

  • scaleX, scaleY

 

Custom attributes

<Constraint>에서 <CustomAttribute> 요소를 사용하여 위치 또는 View 속성과 관련되지 않은 속성의 전환을 지정할 수 있습니다.

<Constraint
    android:id="@+id/button" ...>
 
    <CustomAttribute
        motion:attributeName="backgroundColor"
        motion:customColorValue="#D81B60"/>
 
</Constraint>

<CustomAttribute>에는 다음과 같은 고유 속성들이 있습니다.

      - motion:attributeName

         필수이며 getter 및 setter 메서드가 있는 객체가 일치해야 합니다. 예를 들어 View에는 default로

         getBackgroundColor() 및 setBackgroundColor() 메서드를 지원하는 backgroundColor를 지원합니다.

 

      - 입력해야 하는 다른 속성은 값 유형을 기반으로 해야 합니다.

         -> motion:customColorValue: 색상

         -> motion:customIntegerValue: 정수

         -> motion:customFloatValue: 부동수

         -> motion:customStringValue: 문자열

         -> motion:customDimension: 측정 기준

         -> motion:customBoolean: TRUE or FALSE

맞춤 속성을 지정할 때 시작 및 종료 <ConstraintSet> 요소 모두에 엔드포인트 값을 정의해야 합니다.

 

위 맞춤속성의 내용을 예를 들어 설명하면 아래와 같습니다.

위 그림과 같이 VIew가 드래그 되면서 색상이 변경되도록 하려면 아래 코드 예시와 같이 <CustomAttribute> 요소를 각 ConstraintSet 요소에 추가합니다.

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

 

Additional MotionLayout attributes

MotionLayout에는 위의 예에 있는 속성 외에도 아래와 같은 속성을 추가로 지정할 수 있습니다.

  • app:applyMotionScene="boolean": MotionScene 적용 여부를 나타냅니다. (default: true)

  • app:showPaths="boolean"" 모션이 실행 중일 대 모션 경로를 표시할지 여부 (default: false)

  • app:progress="float": 0 ~ 1까지의 전환 진행 상황을 명시적으로 지정할 수 있습니다.

  • app:currentState="reference": 특정 ConstraintSet을 지정할 수 있습니다.

  • app:motionDebug: 모션에 관한 추가 디버그 정보를 표시할 수 있습니다.  (SHOW_PREGRESS, SHOW_PATH, SHOW_ALL)

'학습' 카테고리의 다른 글

MotionLayout - entrance scene sample 분석  (0) 2020.11.25
MotionLayout - xml 구성요소  (0) 2020.11.25
UI Test 적용하기  (0) 2020.11.25
우선 UNIT Test부터 적용하기  (0) 2020.11.25
테스트 자동화 어떻게 만들까?  (0) 2020.11.25
Comments