Android에서 Floating Action Button 이하 Fab는 굉장히 자주 사용되는 Widget 중 하나입니다.
현재 사이드 프로젝트로 개발 중인 게임 앱에서도 UI/UX 디자인적 고민을 하다 결국 Fab를 사용하기로 결정했는데, 그 사용법이 이전과는 조금 다릅니다.
이전에는 그냥 우측 하단에 버튼을 위치시키고, 사용자가 버튼을 누르면 무언가 액션을 취하는 식으로 아주 심플하게 사용했는데
이번에는 해당 버튼을 누르면 그 위로 다수의 Fab이 나타나게 구현하려고 합니다. 결과적으로 아래와 같은 UI를 만들려고 합니다.

1. 우선 3개의 Fab를 정의합니다. (res/layout/activity_main.xml)
<androidx.constraintlayout.widget.ConstraintLayout
...>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fabSub1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:src="@drawable/ic_lock"
app:fabSize="mini"
app:layout_constraintTop_toTopOf="@id/fabMain"
app:layout_constraintBottom_toBottomOf="@id/fabMain"
app:layout_constraintStart_toStartOf="@id/fabMain"
app:layout_constraintEnd_toEndOf="@id/fabMain"/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fabSub2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:src="@drawable/ic_shopping_cart"
app:fabSize="mini"
app:layout_constraintTop_toTopOf="@id/fabMain"
app:layout_constraintBottom_toBottomOf="@id/fabMain"
app:layout_constraintStart_toStartOf="@id/fabMain"
app:layout_constraintEnd_toEndOf="@id/fabMain"/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fabMain"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="24dp"
android:src="@drawable/ic_add"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
3개 Fab의 constraint 제약들을 살펴보면 모드 fabMain과 같은 위치에 존재하게 됩니다.
결과적으로 위 상태에서 앱을 실행해보면 fabSub1, fabSub2 버튼은 fabMain에 가려져 보이지 않는 상태입니다. code로 각 버튼들에 setOnClickListener를 붙여 로그를 찍어봐도 fabMain이 모든 click event를 앞에서 먹어버리기 때문에 fabSub1, 2는 무용지물인 상태이죠.
2. 애니메이션 구현
fabMain 뒤에 가려져 있는 2개의 sub 버튼들에 애니메이션을 적용할 차례입니다. 적용할 애니메이션은 fabMain의 위로 스윽 나오는 애니메이션으로 코드는 다음과 같습니다.
ObjectAnimator.ofFloat(fabSub1, "translationY", -200f).apply { start() }
ObjectAnimator.ofFloat(fabSub2, "translationY", -400f).apply { start() }
ofFloat 함수는 View, String, float type의 3개 인자를 취하고 있습니다.
- View는 애니메이션을 적용할 View인 fabSub1, 2를 넣어주면 되고,
- String에는 애니메이션의 이동 방향을 의미하는 것 같습니다.
여기서는 위로 나타나게 할 것이므로 translationY 라고 지정해주었습니다. 이와 다르게 수평 이동을 생각한다면 translationX라고 하면 됩니다. 이 값은 정해진 값으로 임의로 바꾸어서는 안될 것 같습니다. - float 값은 얼마만큼 이동시킬지를 나타내는 값입니다.
위 코드는 Fab버튼을 위로 이동시켜 나타나게 하는데 값이 음수인 것이 의아할 수도 있습니다만, (0, 0) 좌표 체계가 좌측 상단부터 시작되는 것으로 보입니다.
반대로 위쪽으로 나타난 버튼들을 다시 아래로 숨기기 위해서는 아래와 같이 작성하면 됩니다.
ObjectAnimator.ofFloat(fabSub1, "translationY", 0f).apply { start() }
ObjectAnimator.ofFloat(fabSub2, "translationY", 0f).apply { start() }
이때는 이동 값을 0f로 하였는데요. 저 역시 처음 적용할 때 올렸던 만큼 다시 내리는 것이니 +200f, +400f로 값을 주었는데, 예상과 달리 위로 올라온 만큼 시작 위치에서 아래로 내려가더군요. 즉 0f로 값을 세팅해주어야 최초 위치로 이동하게 된다는 것을 의미하는 것 같습니다.
이게 끝입니다.
어렵지 않을까 싶었는데 생각보다 간단합니다.
전체 코드는 아래 github repo를 참고하세요.
https://github.com/yoonhok524/Android-Sandbox/tree/master/FabCustom
'개발 > Android' 카테고리의 다른 글
[Android] Resource XML에서 API Key 다루는 방법 (0) | 2020.11.08 |
---|---|
Android 앱 개발 시 Gradle을 통해 API Key 관리하는 방법 (0) | 2020.11.08 |
[Android] Kakao Map 적용해보기 (0) | 2020.11.08 |
갤럭시 S7에서 CameraX 사용 시 앱 죽는 문제 – Bad method handle type 7 (0) | 2020.11.08 |
현재 위치 정보 얻기 – FusedLocationProvider (0) | 2020.11.08 |