page.title=사용자지정 애니메이션의 정의 @jd:body

이 과정에서 다루는 내용

  1. 사용자지정 터치 피드백
  2. 표시 효과 사용
  3. 사용자지정 액티비티 전환
  4. 뷰 상태 변경 애니메이트
  5. 벡터 드로어블 애니메이트

필독 항목

머티리얼 디자인에서 애니메이션은 사용자에게 자신의 동작에 대한 피드백을 제공하고, 앱과 상호작용할 때 시각적 연속성을 제공합니다. 머티리얼 테마는 버튼 및 액티비티 전환을 위한 몇 가지 기본 애니메이션을 제공합니다. Android 5.0(API 레벨 21) 이상에서는 이러한 애니메이션을 사용자가 지정하거나 새로운 애니메이션을 만들 수 있습니다.

사용자지정 터치 피드백

머티리얼 디자인의 터치 피드백은 사용자가 UI 요소와 상호작용하는 시점에서 즉시 시각적으로 확인할 수 있습니다. 버튼의 기본 터치 피드백 애니메이션은 물결 효과를 통해 서로 다른 상태 간에 전환하는 새 {@link android.graphics.drawable.RippleDrawable} 클래스를 사용합니다.

대부분의 경우, 다음과 같이 뷰 배경을 지정하는 방식으로 뷰 XML에서 이 기능을 적용해야 합니다.

참고: selectableItemBackgroundBorderless는 API 레벨 21에서 새로 도입된 특성입니다.

또는 ripple 요소를 사용하여 {@link android.graphics.drawable.RippleDrawable} 을 XML 리소스로 정의할 수 있습니다.

{@link android.graphics.drawable.RippleDrawable} 객체에 색상을 지정할 수 있습니다. 기본 터치 피드백 색상을 변경하려면 테마의 android:colorControlHighlight 특성을 사용합니다.

자세한 내용은 {@link android.graphics.drawable.RippleDrawable} 클래스의 API 레퍼런스를 참조하세요.

표시 효과 사용

표시 애니메이션은 UI 요소 그룹을 표시하거나 숨길 때 사용자에게 시각적 연속성을 제공합니다. {@link android.view.ViewAnimationUtils#createCircularReveal ViewAnimationUtils.createCircularReveal()} 메서드를 사용하면 클리핑 서클을 애니메이트하여 뷰를 표시하거나 숨길 수 있습니다.

이 효과를 사용하여 이전에 보이지 않았던 뷰를 표시하려면:

// previously invisible view
View myView = findViewById(R.id.my_view);

// get the center for the clipping circle
int cx = (myView.getLeft() + myView.getRight()) / 2;
int cy = (myView.getTop() + myView.getBottom()) / 2;

// get the final radius for the clipping circle
int finalRadius = Math.max(myView.getWidth(), myView.getHeight());

// create the animator for this view (the start radius is zero)
Animator anim =
    ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0, finalRadius);

// make the view visible and start the animation
myView.setVisibility(View.VISIBLE);
anim.start();

이 효과를 사용하여 이전에 보였던 뷰를 숨기려면:

// previously visible view
final View myView = findViewById(R.id.my_view);

// get the center for the clipping circle
int cx = (myView.getLeft() + myView.getRight()) / 2;
int cy = (myView.getTop() + myView.getBottom()) / 2;

// get the initial radius for the clipping circle
int initialRadius = myView.getWidth();

// create the animation (the final radius is zero)
Animator anim =
    ViewAnimationUtils.createCircularReveal(myView, cx, cy, initialRadius, 0);

// make the view invisible when the animation is done
anim.addListener(new AnimatorListenerAdapter() {
    @Override
    public void onAnimationEnd(Animator animation) {
        super.onAnimationEnd(animation);
        myView.setVisibility(View.INVISIBLE);
    }
});

// start the animation
anim.start();

사용자지정 액티비티 전환

그림 1 - 공유 요소를 이용한 전환.

영화를 재생하려면 기기 화면을 클릭하세요.

머티리얼 디자인 앱의 액티비티 전환은 공통 요소 간의 모션 및 변환을 통해 서로 다른 상태 간에 시각적 연결을 제공합니다. 들어가기 및 나가기 전환과 액티비티 간 공유 요소의 전환을 위한 사용자지정 애니메이션을 지정할 수 있습니다.

Android 5.0(API 레벨 21)은 다음 들어가기 및 나가기 전환을 지원합니다.

{@link android.transition.Visibility} 클래스를 확장하는 모든 전환은 들어가기 또는 나가기 전환으로 지원됩니다. 자세한 내용은 {@link android.transition.Transition} 클래스의 API 레퍼런스를 참조하세요.

Android 5.0(API 레벨 21)은 다음의 공유 요소 전환도 지원합니다.

앱에서 액티비티 전환을 활성화할 경우, 들어가기 및 나가기 액티비티 간에 기본 크로스페이딩(cross-fading) 전환이 활성화됩니다.

  그림 2 - 하나의 공유 요소로 장면 전환.

사용자지정 전환 지정

먼저 머티리얼 테마에서 상속하는 스타일을 정의할 때, android:windowContentTransitions 특성을 통해 창 콘텐츠 전환을 활성화합니다. 들어가기, 나가기 및 공유 요소 전환도 스타일 정의에서 지정할 수 있습니다.

<style name="BaseAppTheme" parent="android:Theme.Material">
  <!-- enable window content transitions -->
  <item name="android:windowContentTransitions">true</item>

  <!-- specify enter and exit transitions -->
  <item name="android:windowEnterTransition">@transition/explode</item>
  <item name="android:windowExitTransition">@transition/explode</item>

  <!-- specify shared element transitions -->
  <item name="android:windowSharedElementEnterTransition">
    @transition/change_image_transform</item>
  <item name="android:windowSharedElementExitTransition">
    @transition/change_image_transform</item>
</style>

이 예에서 change_image_transform 전환은 다음과 같이 정의됩니다.

<!-- res/transition/change_image_transform.xml -->
<!-- (see also Shared Transitions below) -->
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
  <changeImageTransform/>
</transitionSet>

changeImageTransform 요소는 {@link android.transition.ChangeImageTransform} 클래스에 해당합니다. 자세한 내용은 {@link android.transition.Transition}의 API 레퍼런스를 참조하세요.

코드에서 창 콘텐츠 전환을 활성화하려면 {@link android.view.Window#requestFeature Window.requestFeature()} 메서드를 호출합니다.

// inside your activity (if you did not enable transitions in your theme)
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);

// set an exit transition
getWindow().setExitTransition(new Explode());

코드에서 전환을 지정하려면 {@link android.transition.Transition} 객체를 사용하여 다음과 같은 메서드를 호출합니다.

{@link android.view.Window#setExitTransition setExitTransition()} 및 {@link android.view.Window#setSharedElementExitTransition setSharedElementExitTransition()} 메서드는 호출하는 액티비티의 나가기 전환을 정의합니다. {@link android.view.Window#setEnterTransition setEnterTransition()} 및 {@link android.view.Window#setSharedElementEnterTransition setSharedElementEnterTransition()} 메서드는 호출되는 액티비티의 들어가기 전환을 정의합니다.

전환 효과를 극대화하려면 호출하는 액티비티와 호출되는 액티비티 모두에서 창 콘텐츠 전환을 활성화해야 합니다. 그렇지 않으면 호출하는 액티비티가 나가기 전환을 시작하지만, 배율 또는 페이드와 같은 창 전환이 나타납니다.

들어가기 전환을 최대한 빨리 시작하려면 호출되는 액티비티에서 {@link android.view.Window#setAllowEnterTransitionOverlap Window.setAllowEnterTransitionOverlap()} 메서드를 사용하세요. 그러면 더욱 인상적인 들어가기 전환이 가능합니다.

전환을 사용하여 액티비티 시작

전환을 활성화하고 액티비티에 대해 나가기 전환을 설정한 경우, 다음과 같이 다른 액티비티를 시작하면 전환이 활성화됩니다.

startActivity(intent,
              ActivityOptions.makeSceneTransitionAnimation(this).toBundle());

두 번째 액티비티에 대해 들어가기 전환을 설정한 경우, 액티비티가 시작되면 전환도 활성화됩니다. 다른 액티비티를 시작할 때 전환을 비활성화하려면 null 옵션 번들을 제공하십시오.

공유 요소를 가진 액티비티 시작

공유 요소를 가진 두 액티비티 간에 화면 전환 애니메이션을 만들려면:

  1. 테마에서 창 콘텐츠 전환을 활성화합니다.
  2. 스타일에서 공유 요소 전환을 지정합니다.
  3. 전환을 XML 리소스로 정의합니다.
  4. android:transitionName 특성을 사용하여 두 레이아웃의 공유 요소에 공통 이름을 지정합니다.
  5. {@link android.app.ActivityOptions#makeSceneTransitionAnimation ActivityOptions.makeSceneTransitionAnimation()} 메서드를 사용합니다.
// get the element that receives the click event
final View imgContainerView = findViewById(R.id.img_container);

// get the common element for the transition in this activity
final View androidRobotView = findViewById(R.id.image_small);

// define a click listener
imgContainerView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Intent intent = new Intent(this, Activity2.class);
        // create the transition animation - the images in the layouts
        // of both activities are defined with android:transitionName="robot"
        ActivityOptions options = ActivityOptions
            .makeSceneTransitionAnimation(this, androidRobotView, "robot");
        // start the new activity
        startActivity(intent, options.toBundle());
    }
});

코드에서 생성하는 공유된 동적 뷰의 경우, {@link android.view.View#setTransitionName View.setTransitionName()} 메서드를 사용하여 두 액티비티의 공통 요소 이름을 지정합니다.

두 번째 액티비티 종료 시, 장면 전환 애니메이션을 되돌리려면 {@link android.app.Activity#finish Activity.finish()} 대신 {@link android.app.Activity#finishAfterTransition Activity.finishAfterTransition()} 메서드를 호출합니다.

여러 공유 요소를 가진 액티비티 시작

2개 이상의 공유 요소를 가진 두 액티비티 간에 적용할 장면 전환 애니메이션을 만들려면 android:transitionName 특성으로 (또는 두 액티비티에서{@link android.view.View#setTransitionName View.setTransitionName()} 메서드를 사용하여) 두 레이아웃의 공유 요소를 정의하고 다음과 같이 {@link android.app.ActivityOptions} 개체를 생성합니다.

ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this,
        Pair.create(view1, "agreedName1"),
        Pair.create(view2, "agreedName2"));

커브 모션 사용

머티리얼 디자인의 애니메이션은 시간 보간 및 공간 이동 패턴에서 커브를 사용합니다. Android 5.0(API 레벨 21) 이상에서 애니메이션의 사용자지정 타이밍 커브 및 커브 모션 패턴을 정의할 수 있습니다.

{@link android.view.animation.PathInterpolator} 클래스는 베지어 곡선 또는 {@link android.graphics.Path} 개체를 기반으로 하는 새 보간기입니다. 이 보간기는 생성자 인수를 사용하여 지정된 기준점 (0,0) 및 (1,1)과 제어점으로 모션 커브를 1x1 정사각형 안에 지정합니다. 또한 경로 보간기를 XML 리소스로 정의할 수도 있습니다.

<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
    android:controlX1="0.4"
    android:controlY1="0"
    android:controlX2="1"
    android:controlY2="1"/>

시스템은 머티리얼 디자인 사양에서 세 가지 기본 커브에 대한 XML 리소스를 제공합니다.

{@link android.view.animation.PathInterpolator} 객체를 {@link android.animation.Animator#setInterpolator Animator.setInterpolator()} 메서드에 전달할 수 있습니다.

{@link android.animation.ObjectAnimator} 클래스에는 한 번에 2개 이상의 속성을 사용하여 경로를 따라 좌표를 애니메이트할 수 있는 새 생성자가 있습니다. 예를 들어 다음 애니메이터는 뷰의 X 및 Y 속성을 애니메이트하기 위해 {@link android.graphics.Path} 객체를 사용합니다.

ObjectAnimator mAnimator;
mAnimator = ObjectAnimator.ofFloat(view, View.X, View.Y, path);
...
mAnimator.start();

뷰 상태 변경 애니메이트

{@link android.animation.StateListAnimator} 클래스를 사용하면 뷰의 상태가 변경될 때 실행되는 애니메이터를 정의할 수 있습니다. 다음 예는 {@link android.animation.StateListAnimator}를 XML 리소스로 정의하는 방법을 보여줍니다.

<!-- animate the translationZ property of a view when pressed -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:state_pressed="true">
    <set>
      <objectAnimator android:propertyName="translationZ"
        android:duration="@android:integer/config_shortAnimTime"
        android:valueTo="2dp"
        android:valueType="floatType"/>
        <!-- you could have other objectAnimator elements
             here for "x" and "y", or other properties -->
    </set>
  </item>
  <item android:state_enabled="true"
    android:state_pressed="false"
    android:state_focused="true">
    <set>
      <objectAnimator android:propertyName="translationZ"
        android:duration="100"
        android:valueTo="0"
        android:valueType="floatType"/>
    </set>
  </item>
</selector>

사용자지정 뷰 상태 애니메이션을 뷰에 첨부하려면 이 예와 같이 XML 리소스 파일의 selector 요소를 사용하여 애니메이터를 정의한 후에 android:stateListAnimator 특성을 통해 뷰에 할당합니다. 코드에서 뷰에 상태 목록 애니메이터를 할당하려면 {@link android.animation.AnimatorInflater#loadStateListAnimator AnimationInflater.loadStateListAnimator()} 메서드를 사용하고, {@link android.view.View#setStateListAnimator View.setStateListAnimator()} 메서드로 애니메이터를 뷰에 할당합니다.

머티리얼 테마를 확장하는 테마의 경우, 버튼은 기본적으로 Z 애니메이션을 가집니다. 버튼에서 이러한 동작을 피하려면 android:stateListAnimator 특성을 @null로 설정합니다.

{@link android.graphics.drawable.AnimatedStateListDrawable} 클래스를 사용하면 연관된 뷰의 상태 변경 사이에 애니메이션을 보여주는 Drawable을 생성할 수 있습니다. Android 5.0의 일부 시스템 위젯은 이러한 애니메이션을 기본적으로 사용합니다. 다음 예는 {@link android.graphics.drawable.AnimatedStateListDrawable}를 XML 리소스로 정의하는 방법을 보여줍니다.

<!-- res/drawable/myanimstatedrawable.xml -->
<animated-selector
    xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- provide a different drawable for each state-->
    <item android:id="@+id/pressed" android:drawable="@drawable/drawableP"
        android:state_pressed="true"/>
    <item android:id="@+id/focused" android:drawable="@drawable/drawableF"
        android:state_focused="true"/>
    <item android:id="@id/default"
        android:drawable="@drawable/drawableD"/>

    <!-- specify a transition -->
    <transition android:fromId="@+id/default" android:toId="@+id/pressed">
        <animation-list>
            <item android:duration="15" android:drawable="@drawable/dt1"/>
            <item android:duration="15" android:drawable="@drawable/dt2"/>
            ...
        </animation-list>
    </transition>
    ...
</animated-selector>

벡터 드로어블 애니메이트

벡터 드로어블은 정의를 잃지 않고 확대할 수 있습니다. {@link android.graphics.drawable.AnimatedVectorDrawable} 클래스를 사용하면 Vector Drawable의 속성을 애니메이트할 수 있습니다.

일반적으로 애니메이트된 벡터 드로어블은 다음 3개의 XML 파일에서 정의합니다.

애니메이트된 벡터 드로어블은 <group><path> 요소의 특성을 애니메이트할 수 있습니다. <group> 요소는 경로 또는 하위 그룹 집합을 정의하며, <path> 요소는 그릴 경로를 정의합니다.

애니메이트할 벡터 드로어블을 정의하는 경우, 애니메이터 정의에서 참조할 수 있도록 android:name 특성을 사용하여 그룹 및 경로에 고유한 이름을 할당합니다. 예:

<!-- res/drawable/vectordrawable.xml -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:height="64dp"
    android:width="64dp"
    android:viewportHeight="600"
    android:viewportWidth="600">
    <group
        android:name="rotationGroup"
        android:pivotX="300.0"
        android:pivotY="300.0"
        android:rotation="45.0" >
        <path
            android:name="v"
            android:fillColor="#000000"
            android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />
    </group>
</vector>

애니메이트된 벡터 드로어블 정의는 벡터 드로어블의 그룹 및 경로를 이름으로 참조합니다.

<!-- res/drawable/animvectordrawable.xml -->
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
  android:drawable="@drawable/vectordrawable" >
    <target
        android:name="rotationGroup"
        android:animation="@anim/rotation" />
    <target
        android:name="v"
        android:animation="@anim/path_morph" />
</animated-vector>

애니메이션 정의는 {@link android.animation.ObjectAnimator} 또는 {@link android.animation.AnimatorSet} 객체를 나타냅니다. 이 예의 첫 번째 애니메이터는 대상 그룹을 360도 회전합니다.

<!-- res/anim/rotation.xml -->
<objectAnimator
    android:duration="6000"
    android:propertyName="rotation"
    android:valueFrom="0"
    android:valueTo="360" />

두 번째 애니메이터는 벡터 드로어블의 경로를 다른 모양으로 모핑합니다. 두 경로 모두 모핑이 가능해야 하며, 같은 수의 명령어와 각 명령어에 대해 같은 수의 매개변수가 있어야 합니다.

<!-- res/anim/path_morph.xml -->
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <objectAnimator
        android:duration="3000"
        android:propertyName="pathData"
        android:valueFrom="M300,70 l 0,-70 70,70 0,0   -70,70z"
        android:valueTo="M300,70 l 0,-70 70,0  0,140 -70,0 z"
        android:valueType="pathType" />
</set>

자세한 내용은 {@link android.graphics.drawable.AnimatedVectorDrawable}의 API 레퍼런스를 참조하세요.