본문 바로가기
Project/안드로이드 프로젝트(HomingBird)

Android Studio, JAVA] 오브젝트가 통통 튀는 애니메이팅

by 김마리님 2020. 12. 1.

결과물 :

(물론 사실 저렇게 길게 걸리는건 UX 적으로 최악이긴 합니다만 연습용이니까요 ^-^♥)

 

물체는 처음에 속도가 빠르게 붙습니다. 이후에 물체가 한번 부딪히며 탄성과 원래대로 돌아오려는 성질때문에 위로 튀어오르게 됩니다. 그러나 튀어오르는 힘은 중력에 의해 서서히 사라지고, 떨어지는 길이가 줄어들며 물체에 적용하는 힘도 적어집니다. 그러니 물체가 찌그러지는 비율도 줄고 서서히 원래 모양으로 멈추게 됩니다. 즉, 떨어지는 물체는 감속이 됩니다. 

이것을 올바르게 작용하기 위해서는 감속곡선이 필요한데요, 좋은 사이트가 있습니다.

cubic-bezier.com/#.06,.63,.51,.98

 

cubic-bezier.com

 

cubic-bezier.com

여기서는 다양한 곡선을 만들어볼 수 있고, 시간을 설정하면 물체의 진행과 속도의 비율을 알 수 있습니다. 즉, 뛰어오르면서 움직이는 전체 길이의 progress를 알 수 있다면, 시간 설정이 가능해진다는 이야기입니다. 

 

다음 사이트에서 약 1초를 기점으로 하트가 떨어지는 감속곡선을 만들고, 길이의 진행률을 progress에 따라 duration과 offset으로 지정합니다.

 

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillAfter="true"
    android:ordering="sequentially">

    <set
        android:duration="160"
        >

        <translate
            android:fromXDelta="0"
            android:fromYDelta="-10%p"
            android:interpolator="@android:interpolator/accelerate_quint"
            android:toXDelta="0"
            android:toYDelta="31%p"
            />

        <scale
            android:fromYScale="1.0"
            android:fromXScale="1.0"
            android:toYScale="0.5"
            android:toXScale="1.2"
            android:pivotX="50%"
            android:pivotY="40%p"

            />

    </set>

    <set
        android:duration="200"
        android:startOffset="160"
        >

        <scale
            android:fromYScale="1.0"
            android:fromXScale="1.0"
            android:toYScale="3.0"
            android:toXScale="0.8"
            android:pivotX="50%"
            android:pivotY="40%p"
            />

        <translate
            android:fromXDelta="0"
            android:toXDelta="20%"
            android:fromYDelta="0"
            android:toYDelta="-10%p"
            android:interpolator="@android:interpolator/accelerate_quint"
            />

        <scale
            android:fromYScale="1.0"
            android:fromXScale="1.0"
            android:toYScale="0.6"
            android:toXScale="1.2"
            android:pivotX="50%"
            android:pivotY="23%p"
            android:startOffset="250"

            />


    </set>

    <set
        android:duration="130"
        android:startOffset="360"
        >

        <scale
            android:fromYScale="1.0"
            android:fromXScale="1.0"
            android:toYScale="1.3"
            android:toXScale="0.8"
            android:pivotX="50%"
            android:pivotY="20%p"
            />


        <translate
            android:fromXDelta="0"
            android:fromYDelta="0%"
            android:interpolator="@android:interpolator/accelerate_quint"
            android:toXDelta="10%"
            android:toYDelta="10%p"
            />


    </set>

    <set
        android:duration="150"
        android:startOffset="490"
        >

        <scale
            android:fromYScale="1.0"
            android:fromXScale="1.0"
            android:toYScale="0.9"
            android:toXScale="1.1"
            android:pivotX="50%"
            android:pivotY="40%p"
            />

        <translate
            android:fromXDelta="0"
            android:fromYDelta="0%"
            android:interpolator="@android:interpolator/accelerate_quint"
            android:toXDelta="10%"
            android:toYDelta="-5%p"
            android:startOffset="50"
            />

    </set>

    <set
        android:duration="90"
        android:startOffset="640"
        >

        <scale
            android:fromYScale="1.0"
            android:fromXScale="1.0"
            android:toYScale="0.9"
            android:toXScale="1.0"
            android:pivotX="50%"
            android:pivotY="40%p"
            />

        <translate
            android:fromXDelta="0"
            android:fromYDelta="0%"
            android:interpolator="@android:interpolator/accelerate_quint"
            android:toXDelta="10%"
            android:toYDelta="5%p"
            />

    </set>

    <set
        android:duration="90"
        android:startOffset="730"
        >
        <translate
            android:fromXDelta="0"
            android:fromYDelta="0%"
            android:interpolator="@android:interpolator/accelerate_quint"
            android:toXDelta="5%"
            android:toYDelta="-3%p"
            />

    </set>

    <set
        android:duration="110"
        android:startOffset="840"
        >
        <translate
            android:fromXDelta="0"
            android:fromYDelta="0%"
            android:interpolator="@android:interpolator/accelerate_quint"
            android:toXDelta="3%"
            android:toYDelta="3%p"
            />

    </set>

    <set
        android:duration="90"
        android:startOffset="930"
        >
        <translate
            android:fromXDelta="0"
            android:fromYDelta="0%"
            android:interpolator="@android:interpolator/accelerate_quint"
            android:toXDelta="1%"
            android:toYDelta="-1%p"
            />

    </set>

    <set
        android:duration="70"
        android:startOffset="1020"
        >
        <translate
            android:fromXDelta="0"
            android:fromYDelta="0%"
            android:interpolator="@android:interpolator/accelerate_quint"
            android:toXDelta="1%"
            android:toYDelta="1%p"
            />

    </set>




</set>

 

이 애니메이션 파일을 value/anim에 만들고(만일 이 파일이 없다면 만들어야 합니다.) 오브젝트에 붙이기만 하면 됩니다.

 

...
	private void fallenHeartAction(){
        Animation animation = AnimationUtils.loadAnimation(getContext(), R.anim.fallen_heart);
        imageViewHeart.setAnimation(animation);
        imageViewHeart.startAnimation(animation);
        DlogUtil.d(TAG, "????");

    }
...
반응형