-
Notifications
You must be signed in to change notification settings - Fork 0
순차적으로 테두리 채우는 애니메이션
HyeonSeongKang edited this page Aug 29, 2023
·
1 revision
안녕하세요. 안드로이드 팀의 강현성
입니다.
이번 프로젝트에서 순차적으로 테두리를 채우는 애니메이션을 구현했는데 어떻게 구현했는지에 대해서 공유하려 합니다.
![](https://private-user-images.githubusercontent.com/68272971/264131198-d1f557a8-13e8-4952-9a94-c2b9ed4c733d.gif?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk5MjA0OTksIm5iZiI6MTczOTkyMDE5OSwicGF0aCI6Ii82ODI3Mjk3MS8yNjQxMzExOTgtZDFmNTU3YTgtMTNlOC00OTUyLTlhOTQtYzJiOWVkNGM3MzNkLmdpZj9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTAyMTglMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwMjE4VDIzMDk1OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTQyZTkzNTlkOWVmOWM0M2RmODhlMzI2NThkZmUyZDg5N2UwODNiYjIwYjM1YzllYWRkMzk1MGFlMTJmOWNhMjYmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.OduGV31A9XVogPF6qjzAb2yajPWY99mBKC4xAiRipxI)
먼저 4개의 뷰를 사용하여 각각의 경계선을 나타낸뒤 조건에 따라 보이거나 숨김 상태로 초기를 세팅합니다. (상, 하, 좌, 우)
<!-- Bottom line -->
<View
android:id="@+id/v_bottom_line"
android:layout_width="match_parent"
android:layout_height="2dp"
android:background="@drawable/shape_bottom_border_line"
android:visibility='@{is_visible == 0 || current_type == "SelfMode" ? View.INVISIBLE : View.VISIBLE}'
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<!-- Right line -->
<View
android:id="@+id/v_right_line"
android:layout_width="2dp"
android:layout_height="match_parent"
android:background="@drawable/shape_right_border_line"
android:visibility='@{is_visible == 0 || current_type == "SelfMode" ? View.INVISIBLE : View.VISIBLE}'
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<!-- Top line -->
<View
android:id="@+id/v_top_line"
android:layout_width="match_parent"
android:layout_height="2dp"
android:background="@drawable/shape_top_border_line"
android:visibility='@{is_visible == 0 || current_type == "SelfMode" ? View.INVISIBLE : View.VISIBLE}'
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<!-- Left line -->
<View
android:id="@+id/v_left_line"
android:layout_width="2dp"
android:layout_height="match_parent"
android:background="@drawable/shape_left_border_line"
android:visibility='@{is_visible == 0 || current_type == "SelfMode" ? View.INVISIBLE : View.VISIBLE}'
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
- 애니메이션 초기화: 현재 실행 중인 모든 애니메이션을 취소하여 충돌을 방지합니다.
binding.vBottomLine.animate().cancel()
binding.vTopLine.animate().cancel()
binding.vLeftLine.animate().cancel()
binding.vRightLine.animate().cancel()
- 경계선 초기 상태 설정: 각 경계선의 스케일 값을 초기화하여 애니메이션을 시작하기 전의 상태로 설정합니다.
binding.vBottomLine.scaleX = 0f
binding.vTopLine.scaleX = 0f
binding.vLeftLine.scaleY = 0f
binding.vRightLine.scaleY = 0f
- 애니메이션 순서 및 동작:
📍 Pivot: View에서의 회전 또는 확대/축소의 중심점을 나타냅니다. 예를 들어, pivotX가 0f일 때 view는 X축에서 왼쪽 끝을 중심으로 확대/축소됩니다.
🔍 scaleX / scaleY: View의 가로 및 세로 크기를 확대/축소하는 데 사용되는 값입니다. 1f는 원래 크기를 나타내며, 0.5f는 원래 크기의 절반을 나타냅니다.
- 상단 경계선 애니메이션: pivotX를 0f로 설정하고, 가로 스케일을 확장합니다.
binding.vTopLine.pivotX = 0f
binding.vTopLine.animate().setDuration(500).scaleX(1f)
- 우측 경계선 애니메이션: 이전 애니메이션 완료 후, pivotY를 0f로 설정하고, 세로 스케일을 확장합니다.
binding.vRightLine.pivotY = 0f
binding.vRightLine.animate().setDuration(500).scaleY(1f)
- 하단 경계선 애니메이션: 이전 애니메이션 완료 후, pivotX를 경계선의 너비로 설정하고, 가로 스케일을 확장합니다.
binding.vBottomLine.pivotX = binding.vBottomLine.width.toFloat()
binding.vBottomLine.animate().setDuration(500).scaleX(1f)
- **좌측 경계선 애니메이션:**이전 애니메이션 완료 후, pivotY를 경계선의 높이로 설정하고, 세로 스케일을 확장합니다.
binding.vLeftLine.pivotY = binding.vLeftLine.height.toFloat()
binding.vLeftLine.animate().setDuration(500).scaleY(1f)
- 반환 값: 함수는 마지막 애니메이션(좌측 경계선 애니메이션)의 ViewPropertyAnimator를 반환합니다.(withEndAction 사용하기 위해)
return binding.vLeftLine.animate()
fun animateBorder(): ViewPropertyAnimator {
binding.vBottomLine.animate().cancel()
binding.vTopLine.animate().cancel()
binding.vLeftLine.animate().cancel()
binding.vRightLine.animate().cancel()
binding.vBottomLine.scaleX = 0f
binding.vTopLine.scaleX = 0f
binding.vLeftLine.scaleY = 0f
binding.vRightLine.scaleY = 0f
binding.vBottomLine.visibility = visibility
binding.vTopLine.visibility = visibility
binding.vLeftLine.visibility = visibility
binding.vRightLine.visibility = visibility
binding.vTopLine.pivotX = 0f
binding.vTopLine.animate()
.setDuration(500)
.scaleX(1f)
.withEndAction {
binding.vRightLine.pivotY = 0f
binding.vRightLine.animate()
.setDuration(500)
.scaleY(1f)
.withEndAction {
binding.vBottomLine.pivotX = binding.vBottomLine.width.toFloat()
binding.vBottomLine.animate()
.setDuration(500)
.scaleX(1f)
.withEndAction {
binding.vLeftLine.pivotY = binding.vLeftLine.height.toFloat()
binding.vLeftLine.animate()
.setDuration(500)
.scaleY(1f)
}
}
}
return binding.vLeftLine.animate() // 마지막 애니메이션의 애니메이터 반환
}
- FE - 나도 오픈소스 개발자? (NPM 배포기)
- FE - 합성 컴포넌트에 스토리북 한 스푼 🥄
- FE - Tailwind CSS 찐하게 사용해보기
- AOS - 안드로이드 네트워크 연결
- AOS - API 요청에 따른 동적 탭 생성
- AOS - 나도 오픈소스 개발자? (jitpack 배포기)
- AOS - 폭죽 애니메이션
- AOS - 가이드 모드 애니메이션
- AOS - 뷰모델과 애니메이션을 같이 사용했을때의 ISSUE
- BE - 무중단 배포에 대해 알아보자!
- BE - 더 무중단스러운 배포를 위한 graceful shutdown
- BE - 쿼리 최적화에 대해 알아보자!
- BE - 실전, 쿼리 가속도 업!