[Android] 증가하는 시간 차 그래프 애니메이션 구현하기 - (3) ViewTreeObserver, OnScrollChangedListener
[Android] 증가하는 시간 차 그래프 애니메이션 구현하기 - (2) ViewTreeObserver, GlobalLayoutListener
[Android] 증가하는 시간 차 그래프 애니메이션 구현하기 - (1) ValueAnimator안드로이드 개발을 하면 할수록 그 어떤 것 보다 예상 소요 시간 , 사용 기술을 확답할 수 없는 것이 바로 처음 보는 UI/UX 를
sxunea.tistory.com
증가하는 시간 차 그래프 애니메이션 구현하기 기록의 마지막 글로, 이전의 글은 위 링크를 클릭하면 참고할 수 있다.
이전 두 개의 포스트를 통해 요구사항 중
- 사용자가 저 뷰를 봤을때 (스크롤해서 내려갔을때) 애니메이션이 시작되게 해주세요.
를 빼고는 모두 구현을 완료했다. 그렇다면 이번 글을 통해 위의 요구사항까지 만족해 구현을 끝내보자.
ViewTreeObserver Listener
Listener | Description |
ViewTreeObserver.OnDrawListener | 뷰가 그려질 때 |
ViewTreeObserver.OnGlobalFocusChangeListener | 뷰 트리의 내의 포커스가 변경될 때 |
ViewTreeObserver.OnGlobalLayoutListener | 뷰 트리의 global layout 상태나 visibility 여부가 변경될 때 |
ViewTreeObserver.OnPreDrawListener | 뷰 트리가 그려지려고 할 때 |
ViewTreeObserver.OnScrollChangedListener | 뷰 트리 항목이 스크롤 되었을 때 |
ViewTreeObserver.OnTouchModeChangeListener | 터치 모드가 변경될 때 |
ViewTreeObserver.OnWindowAttachListener | 뷰 트리가 window에 attach 되거나 detach될 때 |
ViewTreeObserver.OnWindowFocusChangeListener | 뷰 트리의 window focus 상태가 변경 될 때 |
이전 글에서 언급했지만, 한번 더 기억할 겸 리스너를 살펴보자.
남은 요구사항은 단 하나, 스크롤의 위치에 따른 UI의 변화이다. 이를 위해서는 위의 리스너 중 onScrollChangedListener를 활용하면된다.
onScrollChangedListener
ViewTreeObserver.OnScrollChangedListener는 Android에서 뷰가 스크롤될 때 이를 감지하고 처리할 수 있는 리스너이다. 주로 스크롤 위치에 따라 UI를 동적으로 업데이트하거나 특정 이벤트를 트리거할 때 사용된다.
이 애니메이션은 하나의 프래그먼트에 존재하고, ScrollView에서 사용자가 이 뷰까지 스크롤 해 내려와야 증가 애니메이션을 실행해야 한다. 이 경우에 OnScrollChangedListener를 사용하면 된다.
바로 구현 코드를 보자.
fun startAnimationOnVisible(
scrollView: ScrollView,
targetView: TextView,
animator: ValueAnimator
) {
scrollView.viewTreeObserver.addOnScrollChangedListener {
// 애니메이션이 이미 실행 중이면 return
if (animator.isRunning) {
return@addOnScrollChangedListener
}
val scrollY = scrollView.scrollY
val location = IntArray(2)
targetView.getLocationOnScreen(location)
// targetView가 ScrollView 내에서 완전히 보이는 경우 애니메이션 시작
if (location[1] > scrollY && location[1] + targetView.height < scrollY + scrollView.height) {
animator.addListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
// 애니메이션 종료 후 추가 작업 가능
}
})
animator.start()
}
}
}
스크롤 이벤트 감지
- ScrollView의 viewTreeObserver를 사용하여 스크롤 변화가 발생할 때마다 리스너를 통해 처리한다.
중복 애니메이션 방지
- isAnimating 배열을 사용하여 특정 뷰가 이미 애니메이션 중인지 확인한다.
- 이때, 중복 실행을 막기 위해, 이미 애니메이션 중이라면 이벤트 처리를 중단한다.
- isRunning 활용
뷰의 위치 확인
- getLocationOnScreen() 메서드를 사용해 targetView의 화면 내 위치를 가져온다.
- 이 값과 ScrollView의 scrollY 값을 비교하여 뷰가 화면에 완전히 노출된 경우에만 애니메이션을 시작한다.
애니메이션 시작 조건
- targetView가 ScrollView의 가시 영역에 완전히 들어왔을 때만 애니메이션을 실행한다.
애니메이션 리스너 등록
- animator에 리스너를 등록하여 애니메이션이 끝날 때 isAnimating 값을 false로 변경한다.
- 이를 통해 같은 뷰에 대한 애니메이션이 중복 실행되지 않도록 한다.
이렇게 ScrollListener를 활용하면 스크롤 위치를 가져와서 원하는 시점에 맞는 동작을 구현할 수 있다.
하지만 ViewTreeObserver의 Listener들을 활용할 때는 리스너가 불필요한 경우에는 리스너를 해제해 주어 리소스 낭비 / 성능 저하를 막아야함을 기억하며 마치자. 끝 !