본문 바로가기
안드로이드 자바

[JAVA][Android] Animation을 활용한 하트 ToggleButton

by teamnova 2021. 5. 29.

SNS를 이용하다 보면 상대방의 포스팅에 좋아요를 눌러보셨죠?

 

안드로이드에서 제공하는 ToggleButton을 이용하면 쉽게 구현이 가능하지만

 

뭔가 부족해 보입니다.

 

이번에는 애니메이션 효과를 넣어준

 

생동감 넘치는 하트버튼을 만들어 보도록 하겠습니다. 

 

 

 

 

이번에는 Android XML Selector를 활용해 볼건데요

 

selector는 이미지의 상태에 따라 값을 설정해주고 컨트롤 해주는 기능을 가지고 있습니다. 

 

selector를 이용하면 코드가 훨씬 간결해지고 불필요한 코드를 줄일 수 있겠죠?

 

 

 

먼저 비워진 하트와 채워진 하트를 가져오겠습니다.

이미지를 바로 drawable 디렉토리에 넣어주면 안됩니다.

 

저희가 사용할 애니메이션은 Vector Animation인데요 

 

그러기 위해서는 Vector Drawable을 사용해야 합니다. 

 

Vector Drawable은 png와 같은 이미지 파일이 아닌 Path 데이터만을 가지고 아이콘/이미지를 그릴 수 있고 애니메이션도 추가할 수 있습니다.

 

 

 

먼저 Vector Drawable을 추가해주기 위해서는

 

res > drawable > new > Drawable Rresource File 로 들어가 줍니다.

 

 

 

그리고 Root element 에 기본값으로 Selector라 표시되어 있는데요 이곳을 Vector로 수정해 줍니다.

 

 

 

그리고 위의 하트 이름을 넣어준  ic_favorite 과 ic_favorite_border를 생성합니다. 

 

 

ic_favorite.xml

<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="24dp"
        android:height="24dp"
        android:viewportWidth="24"
        android:viewportHeight="24">
    <path
        android:fillColor="@color/pink_700"
        android:pathData="M12,21.35l-1.45,-1.32C5.4,15.36 2,12.28 2,8.5 2,5.42 4.42,3 7.5,3c1.74,0 3.41,0.81 4.5,2.09C13.09,3.81 14.76,3 16.5,3 19.58,3 22,5.42 22,8.5c0,3.78 -3.4,6.86 -8.55,11.54L12,21.35z"/>
</vector>

 

 

ic_favorite_border.xml

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24.0"
    android:viewportHeight="24.0">
    <path
    android:fillColor="@color/pink_700"
    android:pathData="M16.5,3c-1.74,0 -3.41,0.81 -4.5,2.09C10.91,3.81 9.24,3 7.5,3 4.42,3 2,5.42 2,8.5c0,3.78 3.4,6.86 8.55,11.54L12,21.35l1.45,-1.32C18.6,15.36 22,12.28 22,8.5 22,5.42 19.58,3 16.5,3zM12.1,18.55l-0.1,0.1 -0.1,-0.1C7.14,14.24 4,11.39 4,8.5 4,6.5 5.5,5 7.5,5c1.54,0 3.04,0.99 3.57,2.36h1.87C13.46,5.99 14.96,5 16.5,5c2,0 3.5,1.5 3.5,3.5 0,2.89 -3.14,5.74 -7.9,10.05z"/>
</vector>

 

그리고 이 두 벡터 이미지를 Toggle 버튼으로 사용하기 위해 위에서 말한 

 

selector를 만들어 줍니다. 

 

 

button_favorite.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable = "@drawable/ic_favorite"
        android:state_checked="true"/>
    <item android:drawable="@drawable/ic_favorite_border"
        android:state_checked="false"/>
</selector>

 

이제 메인 액티비티로 가보겠습니다. 

 

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ToggleButton
        android:id="@+id/button_favorite"
        android:layout_width="160dp"
        android:layout_height="160dp"
        android:background="@drawable/button_favorite"
        android:checked="false"
        android:text=""
        android:textOff=""
        android:textOn=""
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

 

애니메이션을 활용하기 위해서는 ScaleAnimation이 필요합니다. 이미지의 스케일을 다루기위한 object 입니다.

scaleAnimation = new ScaleAnimation(0.7f, 1.0f, 0.7f, 1.0f, Animation.RELATIVE_TO_SELF, 0.7f, Animation.RELATIVE_TO_SELF, 0.7f);

 

 fromXScale : 시작하는 X 의 크기

 toXScale : 끝나는 시점의 X 크기.

 fromYScale : 시작하는 Y 의 크기.

 toYScale : 끝나는 시점의 Y 크기

 pivotX : X 좌표의 중심점

 pivotY : Y 좌표의 중심점

 duration : 애니메이션 적용 시간

 repeatCount : 반복 횟수

 repeatMode : 반복시 다시 생성될 때 방향

 

 

 

그리고 애니메이션이 일어나는 동안의 횟수, 속도를 조절하거나 시작과 종료시의 효과를 추가하기 위한 interpolator 중 BounceInterpolator를 설정합니다.

 

bounceInterpolator = new BounceInterpolator();
scaleAnimation.setInterpolator(bounceInterpolator);

 

그다음 버튼에 대한 이벤트 리스너를 등록해 주겠습니다.

 

button_favorite 은 CompoundButton으로 정의해줍니다.

 

 

CompoundButton 는 Button의 하위 클래스로 checked와 unchecked의 두가지 상태를 가지고 있는 버튼입니다.

 

CompoundButton button_favorite;

...

 button_favorite = findViewById(R.id.button_favorite);

        button_favorite.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
                compoundButton.startAnimation(scaleAnimation);
            }
        });

 

 

MainActivity.java

 

package com.example.lottieheart;

import androidx.appcompat.app.AppCompatActivity;

import android.animation.Animator;
import android.os.Bundle;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.BounceInterpolator;
import android.view.animation.ScaleAnimation;
import android.widget.Button;
import android.widget.CompoundButton;


public class MainActivity extends AppCompatActivity {

    ScaleAnimation scaleAnimation;
    BounceInterpolator bounceInterpolator;//애니메이션이 일어나는 동안의 회수, 속도를 조절하거나 시작과 종료시의 효과를 추가 할 수 있다
    CompoundButton button_favorite;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        scaleAnimation = new ScaleAnimation(0.7f, 1.0f, 0.7f, 1.0f, Animation.RELATIVE_TO_SELF, 0.7f, Animation.RELATIVE_TO_SELF, 0.7f);

        scaleAnimation.setDuration(500);
        bounceInterpolator = new BounceInterpolator();
        scaleAnimation.setInterpolator(bounceInterpolator);

        button_favorite = findViewById(R.id.button_favorite);

        button_favorite.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
                compoundButton.startAnimation(scaleAnimation);
            }
        });
    }
}

 

 

한층더 업그레이드된

 

하트버튼이 완성되었습니다!!