[Android/Kotlin] Floating Button Animation

Notepad96

·

2022. 9. 8. 19:10

300x250

 

 

1. 요약

 

결과

 

이번 글에서는 Floting Button Animation을 구현하는 방법에 관하여 알아본다.

 

구성은 4개의 Floating Button을 사용하며, 처음에는 1개의 Floating Button만이 보이며 이를 Click 하였을 때 숨겨져 있던 나머지 3개의 Floating Button이 나타나 사용할 수 있도록 하였다.

 

 

이때, Floating Button은 이동하는 Animation 뿐만 아니라 실제로 숨겨져 있는 Floating Button이 이동(Translation)되어야만 사용이 가능하므로 ObjectAnimator를 사용하였다.

 

 

 

 

2. 레이아웃

2-1. activity_main.xml

메인 레이아웃으로서 Floating Button 4개를 사용하여 구성하였다.

 

Layout으로는 RelativeLayout을 사용하였으며 1개의 Floating Button을 Click 하였을 경우 나머지 Floating Button이 나타나도록 하기 위해서 우선 처음에는 나머지 Floating Button이 1개의 Floating Button 아래 덮어져 안 보이도록 구성하였다.

 

여기서 보면 Floating Button 1을 가장 마지막 부분의 선언해주었는데 이렇게 함으로써 z-index 값이 가장 높게 되어 나머지 Floating Button 덮어 씌우고 가장 위의 위치하게 된다.

 

activity_main.xml

 

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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">

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/floating02"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:backgroundTint="#FF8989"
        android:layout_alignParentBottom="true"
        android:layout_alignParentEnd="true"
        android:layout_marginBottom="15dp"
        android:layout_marginRight="15dp"
        app:borderWidth="0dp"
        app:fabSize="mini"
        android:src="@drawable/ic_baseline_discord_24" />

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/floating03"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:backgroundTint="#FF8989"
        android:layout_alignParentBottom="true"
        android:layout_alignParentEnd="true"
        android:layout_marginBottom="15dp"
        android:layout_marginRight="15dp"
        app:borderWidth="0dp"
        app:fabSize="mini"
        android:src="@drawable/ic_baseline_dark_mode_24" />

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/floating04"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:backgroundTint="#FF8989"
        android:layout_alignParentBottom="true"
        android:layout_alignParentEnd="true"
        android:layout_marginBottom="15dp"
        android:layout_marginRight="15dp"
        app:borderWidth="0dp"
        app:fabSize="mini"
        android:src="@drawable/ic_baseline_code_24" />


    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/floating01"
        android:layout_width="64dp"
        android:layout_height="64dp"
        android:backgroundTint="#FF8989"
        android:layout_alignParentBottom="true"
        android:layout_alignParentEnd="true"
        android:layout_marginBottom="10dp"
        android:layout_marginRight="10dp"
        app:borderWidth="0dp"
        app:maxImageSize="32dp"
        android:src="@drawable/ic_baseline_add_24" />

</RelativeLayout>

 

 

 

 

3. 코드 및 설명

3-1. MainActivity.kt

Floating Button 1을 클릭하였을 경우 나머지 Floating Button이 나타나여 사용할 수 있도록 코드를 구현해야 한다.

 

하지만 여기서는 여기서는 Floating Button이 나타나도록 하는 Animation 뿐만 아니라 Floating Button 1 아래 숨겨져 있는 나머지 Button들이 실제로 옮겨져야만 한다.

 

 

Animation 처리만 하기 위해서는 TranslateAnimation을 사용할 수 있지만 실제로 Floating Button들이 이동해야 하므로 ObjectAnimator를 사용한다.

 

 

 

ObjectAnimator.ofFloat(binding.floating02, "translationX", -200f).setDuration(500)

각 인수 값은 (Target View, Property, Values)이며 Property를 보면 translationX가 들어가 있다. 이는 X축으로 이동하기 위한 Property이다. Value는 이동하고자 하는 값으로 px 단위이다.

 

 

이렇듯 원하는 동작을 할 수 있도록 ObjectAnimator를 정의해놓은 후 Click Event가 발생할 때마다 start()를 사용하여 "Object의 Translation + Animation"을 실행하면 된다.

 

 

package com.notepad96.floatinganimation

import android.animation.ObjectAnimator
import android.animation.PropertyValuesHolder
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.notepad96.floatinganimation.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {
    private val binding: ActivityMainBinding by lazy { ActivityMainBinding.inflate(layoutInflater) }
    private var isOpened = false

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(binding.root)

        val floatBtn02AniOut = ObjectAnimator.ofFloat(binding.floating02, "translationX", -200f).setDuration(500)
        val floatBtn02AniIn = ObjectAnimator.ofFloat(binding.floating02, "translationX", 0f).setDuration(500)
        val floatBtn04AniOut = ObjectAnimator.ofFloat(binding.floating04, "translationY", -200f).setDuration(500)
        val floatBtn04AniIn = ObjectAnimator.ofFloat(binding.floating04, "translationY", 0f).setDuration(500)

        val txOut = PropertyValuesHolder.ofFloat("translationX", -150f)
        val tyOut = PropertyValuesHolder.ofFloat("translationY", -150f)
        val floatBtn03AniOut = ObjectAnimator.ofPropertyValuesHolder(binding.floating03, txOut, tyOut).setDuration(500)

        val txIn = PropertyValuesHolder.ofFloat("translationX", 0f)
        val tyIn = PropertyValuesHolder.ofFloat("translationY", 0f)
        val floatBtn03AniIn = ObjectAnimator.ofPropertyValuesHolder(binding.floating03, txIn, tyIn).setDuration(500)


        binding.floating01.setOnClickListener {
            if(isOpened) {
                binding.floating01.setImageResource(R.drawable.ic_baseline_add_24)
                floatBtn02AniIn.start()
                floatBtn03AniIn.start()
                floatBtn04AniIn.start()
            } else {
                binding.floating01.setImageResource(R.drawable.ic_baseline_keyboard_arrow_down_24)
                floatBtn02AniOut.start()
                floatBtn03AniOut.start()
                floatBtn04AniOut.start()
            }
            isOpened = !isOpened
        }

        binding.floating02.setOnClickListener { Toast.makeText(applicationContext, "Click 2!", Toast.LENGTH_SHORT).show() }
        binding.floating03.setOnClickListener { Toast.makeText(applicationContext, "Click 3!", Toast.LENGTH_SHORT).show() }
        binding.floating04.setOnClickListener { Toast.makeText(applicationContext, "Click 4!", Toast.LENGTH_SHORT).show() }
    }
}

 

추가적으로 Floating Button 3의 경우에는 2, 4와 다르게 먼저 PropertyValuesHolder를 통하여 Property를 따로 정의해주고 있다.

 

이는 2가지 각각의 Property와 Value를 동시에 사용하기 위한 방법으로서 여기서는 X축과 Y축 동시에 이동하기 위하여 다음과 같이 정의하였다.

 

정의한 Property를 ObjectAnimator의 ofPropertyValueHolder를 사용하여 묶어 실행함으로써 대각선으로 이동하도록 동작하게 된다.

 

 

 

 

4. 전체 파일

 

 

GitHub - Notepad96/BlogExample02

Contribute to Notepad96/BlogExample02 development by creating an account on GitHub.

github.com

 

 

300x250