애니메이션과 함께 뷰 이동

Compose 방식 사용해 보기
Jetpack Compose는 Android를 위한 권장 UI 도구 키트입니다. Compose에서 애니메이션을 사용하는 방법을 알아봅니다.

백그라운드에서의 사용자 상호작용이나 처리로 인해 화면의 객체를 재배치해야 하는 경우가 많습니다. 객체 위치를 업데이트하면 한 영역에서 다른 영역으로 깜박임이 발생하므로 이 방식 대신 애니메이션을 사용하여 객체를 시작 위치에서 끝 위치로 이동합니다.

Android에서 화면에서 뷰 객체의 위치를 변경할 수 있는 한 가지 방법은 ObjectAnimator를 사용하는 것입니다. 객체가 놓일 종료 위치와 애니메이션 재생 시간을 제공합니다. 시간 보간기를 사용하여 애니메이션의 가속 또는 감속을 제어할 수도 있습니다.

ObjectAnimator로 뷰 위치 변경

ObjectAnimator API는 지정된 시간 동안 뷰의 속성을 변경하는 방법을 제공합니다. 이 API에는 애니메이션하는 속성 유형에 따라 ObjectAnimator의 인스턴스를 만드는 정적 메서드가 포함되어 있습니다. 화면에서 뷰 위치를 변경할 때는 translationXtranslationY 속성을 사용합니다.

다음은 2초 동안 화면 왼쪽에서 100픽셀 떨어진 위치로 뷰를 이동하는 ObjectAnimator의 예입니다.

Kotlin

ObjectAnimator.ofFloat(view, "translationX", 100f).apply {
    duration = 2000
    start()
}

자바

ObjectAnimator animation = ObjectAnimator.ofFloat(view, "translationX", 100f);
animation.setDuration(2000);
animation.start();

변환 값이 부동 소수점 수여야 하므로 이 예에서는 ObjectAnimator.ofFloat() 메서드를 사용합니다. 첫 번째 매개변수는 애니메이션을 적용할 뷰입니다. 두 번째 매개변수는 애니메이션하는 속성입니다. 뷰를 가로로 이동해야 하므로 translationX 속성이 사용됩니다. 마지막 매개변수는 애니메이션의 끝 값입니다. 이 예에서 값 100은 화면 왼쪽으로부터 몇 픽셀 떨어진 위치를 나타냅니다.

다음 메서드는 애니메이션의 재생 시간을 밀리초 단위로 지정합니다. 이 예에서 애니메이션은 2초 (2, 000밀리초) 동안 실행됩니다.

마지막 메서드는 애니메이션을 실행하여 화면에서 뷰의 위치를 업데이트합니다.

ObjectAnimator 사용에 관한 자세한 내용은 ObjectAnimator를 사용하여 애니메이션화를 참고하세요.

곡선 모션 추가

ObjectAnimator를 사용하는 것이 편리하지만 기본적으로 시작점과 종료점 사이의 직선을 따라 뷰의 위치가 변경됩니다. 머티리얼 디자인은 화면에서 객체의 공간 이동과 애니메이션 시간에 곡선을 사용합니다. 곡선 모션을 사용하면 앱에 질감을 더 부여할 수 있고 애니메이션을 좀 더 흥미롭게 만들 수 있습니다.

자체 경로 정의

ObjectAnimator 클래스에는 경로와 함께 한 번에 두 개 이상의 속성을 사용하여 좌표에 애니메이션을 적용할 수 있는 생성자가 있습니다. 예를 들어 다음 애니메이터는 Path 객체를 사용하여 뷰의 X 및 Y 속성에 애니메이션을 적용합니다.

Kotlin

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    val path = Path().apply {
        arcTo(0f, 0f, 1000f, 1000f, 270f, -180f, true)
    }
    val animator = ObjectAnimator.ofFloat(view, View.X, View.Y, path).apply {
        duration = 2000
        start()
    }
} else {
    // Create animator without using curved path
}

자바

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  Path path = new Path();
  path.arcTo(0f, 0f, 1000f, 1000f, 270f, -180f, true);
  ObjectAnimator animator = ObjectAnimator.ofFloat(view, View.X, View.Y, path);
  animator.setDuration(2000);
  animator.start();
} else {
  // Create animator without using curved path
}

다음은 원호 애니메이션의 모습입니다.

그림 1. 곡선 경로 애니메이션.

Interpolator은 이징 곡선의 구현입니다. 이완 곡선 개념에 관한 자세한 내용은 Material Design 문서를 참고하세요. Interpolator는 애니메이션의 특정 값이 시간 함수로 계산되는 방식을 정의합니다. 시스템은 Material Design 사양에서 세 가지 기본 커브에 대한 XML 리소스를 제공합니다.

  • @interpolator/fast_out_linear_in.xml
  • @interpolator/fast_out_slow_in.xml
  • @interpolator/linear_out_slow_in.xml

PathInterpolator 사용

PathInterpolator 클래스는 Android 5.0(API 21)에 도입된 보간기입니다. 이 그래프는 베지어 곡선 또는 Path 객체를 기반으로 합니다. 이징을 위한 머티리얼 디자인 문서의 Android 예에서는 PathInterpolator를 사용합니다.

PathInterpolator에는 다양한 유형의 베지어 곡선을 기반으로 하는 생성자가 있습니다. 모든 베지어 곡선은 각각 (0,0)(1,1)에 고정된 시작점과 끝점이 있습니다. 다른 생성자 인수는 생성되는 Bzier 곡선의 유형에 따라 다릅니다.

예를 들어 이차 베지어 곡선의 경우 한 제어점의 X 및 Y 좌표만 있으면 됩니다.

Kotlin

val myInterpolator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    PathInterpolator(0.67f, 0.33f)
} else {
    LinearInterpolator()
}

자바

Interpolator myInterpolator = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  myInterpolator = new PathInterpolator(0.67f, 0.33f);
} else {
  myInterpolator = new LinearInterpolator();
}

이렇게 하면 빠르게 시작했다가 끝에 가까워질수록 감속하는 이징 곡선이 생성됩니다.

cubic Bézier 생성자도 마찬가지로 시작점과 끝점이 고정되어 있지만 두 개의 제어점이 필요합니다.

Kotlin

val myInterpolator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    PathInterpolator(0.5f, 0.7f, 0.1f, 1.0f)
} else {
    LinearInterpolator()
}

자바

Interpolator myInterpolator = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  myInterpolator = new PathInterpolator(0.5f, 0.7f, 0.1f, 1.0f);
} else {
  myInterpolator = new LinearInterpolator();
}

Material Design 강조된 감속 완화 곡선의 구현입니다.

더 세부적으로 제어하려면 임의의 Path를 사용하여 곡선을 정의할 수 있습니다.

Kotlin

val myInterpolator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  val path = Path().apply {
    moveTo(0.0f, 0.0f)
    cubicTo(0.5f, 0.7f, 0.1f, 1.0f, 1.0f, 1.0f)
  }
  PathInterpolator(path)
} else {
  LinearInterpolator()
}

자바

Interpolator myInterpolator = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  Path path = new Path();
  path.moveTo(0.0f, 0.0f);
  path.cubicTo(0.5f, 0.7f, 0.1f, 1.0f, 1.0f, 1.0f);
  myInterpolator = new PathInterpolator(path);
} else {
  myInterpolator = new LinearInterpolator();
}

이렇게 하면 3차원 베지어 예와 동일한 이징 곡선이 생성되지만 Path를 대신 사용합니다.

또한 경로 보간 유형을 XML 리소스로 정의할 수도 있습니다.

<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
    android:controlX1="0.5"
    android:controlY1="0.7"
    android:controlX2="0.1f"
    android:controlY2="1.0f"/>

PathInterpolator 객체를 만든 후 Animator.setInterpolator() 메서드에 전달할 수 있습니다. Animator는 시작 시 보간기를 사용하여 타이밍 또는 경로 곡선을 결정합니다.

Kotlin

val animation = ObjectAnimator.ofFloat(view, "translationX", 100f).apply {
    interpolator = myInterpolator
    start()
}

Java

ObjectAnimator animation = ObjectAnimator.ofFloat(view, "translationX", 100f);
animation.setInterpolator(myInterpolator);
animation.start();