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

아이콘 클릭 시 종처럼 흔들리는 애니메이션 효과 주기 본문

android Tip

아이콘 클릭 시 종처럼 흔들리는 애니메이션 효과 주기

길재의 그 정신으로 공부하자 2021. 4. 7. 12:14

안드로이드에서 animaion을 처리하는 방법은 크게 3가지로 나뉩니다.

Animation을 사용하는 방법과 Animator를 사용하는 방법 그리고 마지막으로 MotionLayout이 있습니다.

안드로이드가 발표되면서 최초로 나온 것이 Animation이고 그후 Animator가 발표되었고 몇년전에 MotionLayout이

발표되었습니다.

 

MotionLayout 관련된 내용은 이전 글 참고 부탁 드리겠습니다.

https://als2019.tistory.com/16

 

 

이 글은 animation과 animtor의 차이에 대해 설명하는 글이 아니라 사용자가 아이콘 클릭 시 종처럼 흔들리는 

애니매이션 효과를 줄 때 사용할 수 있는 다양한 방법에 대해 설명하기 위한 것입니다.

 

방법은 한가지만 있는 것이 아니므로 굳이 한가지 방법만 고집할 필요는 없습니다.

 

또 굳이 종처럼 흔들리는 애니메이션 효과를 기준으로 설명하는 이유는 단순히 단 방향성을 가진 애니메이션 처리로는

animation이나 animator에 대해 설명하기가 미흡하기 때문 입니다.

 

오늘 설명할 부분은 종처럼 흔들리는 애니메이션 효과 처리 입니다.

 

설명에 집중하기 위해 Interpolation, alpha, ...등과 같이 부수적인 내용은 모두 삭제하였습니다.

 

방법 1. animation-list 사용하기

anim 폴더에 vibrate.xml을 만들고 animation-list을 사용하여 여러 이미지를 사용해 종처럼 흔들리는 애니메이션 효과를

사용할 수도 있지만 그렇게 되면 많은 수의 이미지가 필요하게 되어 그리 효율적인 방법은 아닙니다.

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
  android:oneshot="false">
  <item android:drawable="@drawable/bell1“ android:duration=“100" />
  <item android:drawable="@drawable/bell2” android:duration="100" />
  <item android:drawable="@drawable/bell3” android:duration="100" />
  <item android:drawable="@drawable/bell4” android:duration="100" />
  <item android:drawable="@drawable/bell5” android:duration="100" />
  <item android:drawable="@drawable/bell6” android:duration="100" />
  <item android:drawable="@drawable/bell7” android:duration="100" />
  <item android:drawable="@drawable/bell8 android:duration="100" />
  <item android:drawable="@drawable/bell9” android:duration="100" />
  <item android:drawable="@drawable/bell10” android:duration="100" />
</animation-list>

 

 

방법 2. 여러 개의 animation 사용하기

한바퀴 회전하거나 점점 커지거나 사라지는 등, 단방향성을 갖는다면 한개의 animation만 사용하면 되지만 

사용자 클릭 시 종처럼 좌우로 흔들려야 하기 때문에 한개의 애니메이션 파일로는 처리할 수 없습니다.

일단 아래와 같이 anim 폴더에 두 개의 animation xml 파일을 만들어줍니다.

 

// vibrate_left.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/accelerate_decelerate_interpolator">
    <rotate
        android:fromDegrees="0"
        android:toDegrees="-30"
        android:pivotX="50%"
        android:pivotY="50%"/>
</set>

// vibrate_right.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/accelerate_decelerate_interpolator">
    <rotate
        android:fromDegrees="0"
        android:toDegrees="30"
        android:pivotX="50%"
        android:pivotY="50%">
</set>

 

위 내용은 대략 이미지의 중심을 기준으로 30도 정도 좌우로 움직이는 애니메이션 입니다.

이걸 순차적으로 두번 반복하도록 해야합니다.

이때 사용해야 하는 것이 AnimationSet 입니다.

AnimationSet을 사용하여 좌우로 두번 실행하는 코드는 아래와 같습니다.

// AnimationSet 인스턴스 생성
val animationSet = AnimationSet(true)

// 왼쪽으로 30도 움직이는 애니메이션 100ms 동안 실행되도록 생성
val left1 = AnimationUtils.loadAnimation(context, R.anim.vibrate_left)
left1.setDuration(100)
// AnimationSet에 추가
animationSet.addAnimation(left1)

// 나머지 3개 애니메이션도 반복
val right1 = AnimationUtils.loadAnimation(context, R.anim.vibrate_right)
right1.setDuration(100)
// AnimationSet에 그냥 넣으면 동시에 실행되므로 두번째 애니메이션은 첫번째 애니메이션이 종료되는 100ms 후에 실행되도록 설정
right1.setStartOffset(100)
animationSet.addAnimation(right1)

val left2 = AnimationUtils.loadAnimation(context, R.anim.vibrate_left)
left2.setDuration(100)
// 두번째 애니메이션 종료 후 실행되도록 설정
left2.setStartOffset(200)
animationSet.addAnimation(left2)

val right2 = AnimationUtils.loadAnimation(context, R.anim.vibrate_right)
right2.setDuration(100)
// 세번째 애니메이션 종료 후 실행되도록 설정
right2.setStartOffset(300)

// view에 애니메이션 적용 (플레이)
view.startAnimation(animationSet)

이렇게하면 사용자 클릭 시 종처럼 흔들리는 애니메이션이 완성됩니다.

애니메이션 동작에는 문제가 없지만 애니메이션 실행 순서를 각 애니메이션이 종료되는 시점을 보고 수동으로 입력해야 하기 때문인지 조금 불편합니다.

 

방법 3. animator 사용하기

앞서 설명한 animation 방식은 anim 폴더에 xml을 만들어야 하는 등 번거로운 작업이 필요합니다.

animator를 사용하면 xml 파일 없이 간편하게 애니메이션 처리가 가능합니다.

우리가 필요한 애니메이션 처리는 Object를 종처럼 좌우로 흔들리는 처리는 하는 것이므로 ObjectAnimator와

AnimatorSet을 사용하도록 하겠습니다.

 

AnimatorSet은 앞서 설명한 AnimationSet과 유사하게 여러개의 애니메이션을 처리할 수 있도록 도와주는 class 입니다.

다른 점은 AnimationSet과는 달리 playSequentially()라는 함수를 지원해 애니메이션을 순차적으로 처리할 수 있다는 부분 입니다.

 

코드는 아래와 같습니다.

// AnimatorSet 인스턴스 생성
val animatorSet = AnimatorSet()
// ObjectAnimator 인스턴스 생성
val objectAnimator1 = ObjectAnimator.ofFloat(view, View.ROTATION, 0f, -30f).setDuration(50)
val objectAnimator2 = ObjectAnimator.ofFloat(view, View.ROTATION, -30f, 30f).setDuration(100)
val objectAnimator3 = ObjectAnimator.ofFloat(view, View.ROTATION, 30f, -30f).setDuration(100)
val objectAnimator4 = ObjectAnimator.ofFloat(view, View.ROTATION, -30f, 0f).setDuration(50)

// 순차적으로 실행될 수 있도록 AnimatorSet에 ObjectAnimator 추가
animatorSet.playSequentially(objectAnimator1, objectAnimator2, objectAnimator3, objectAnimator4)

// 애니메이션 시작
animatorSet.start()

 

마무리

이 글에서 애니메이션 처리 3가지 방법에 대해 설명하였습니다.

첫번째 방식은 사람이 달려가는 애니메이션 처럼 프로그램으로 처리하기 곤란한 애니메이션 처리에 효율적인 방식이며

두번째 방식은 별도의 xml을 생성하므로 단순한 애니메이션 효과를 재활용할 때 효과적입니다.

세번째 방식은 애니메이션을 다양하게 만들고 조합이 가능하므로 복잡한 애니메이션 처리에 효과적 입니다.

 

Animation과 Animator는 이 글에 설명된 것 이외에도 더 많은 효과 사용 방법을 가지고 있습니다.

이 글을 보고 궁금하신 분들은 언제 작성할지 모르는 제 후속 글을 하염없이 기다리지 마시고… ㅠ_ㅠ

 

구글에 검색하면 됩니다. ^_______^

 

 

번외 방법. 한개 animation만 사용해서 문제 해결하기 @_@;;

위에서 거창하게 설명했지만 종처럼 흔들리는 효과도 좌우로 반복되기 때문에  한개 animation만 사용해서 처리가 가능합니다.

아래와 같이 repeatMode와 repeatCount속성을 사용하면 됩니다.

// vibrate.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/accelerate_decelerate_interpolator">
    <rotate
        android:duration="100"
        android:fromDegrees="-30"
        android:toDegrees="30"
        android:pivotX="50%"
        android:pivotY="50%"
        android:repeatCount="1"
        android:repeatMode="reverse"/>
</set>

그리고 사용 시 아래와 같이 두 줄만 추가해주면 되므로 매우 간단합니다.

Animation vibrate = AnimationUtils.loadAnimation(ActHotPlace.this, R.anim.vibrate);
view.startAnimation(vibrate);

 

위 방법들보다 이게 제일 심플한 해결 방법입니다.

하지만 이 방법을 번외로 뺀 이유는 -30에서 시작해서 30도로 끝나는 애니메이션이다보니 아무래도 애니메이션 효과가 다른 방법에 비해 매끄럽지 못하기 때문 입니다. ^___^;;;

Comments