왼쪽의 이미지에서 날짜를 누르면 우측 화면으로 바뀐다. 다시 달력을 보여주기 위해 뭔가 액션을 취해야했는데, 내가 생각한 방법은 총 3개다.
- 바텀시트 behavior를 사용한다(리사이클러뷰에 behavior를 bottom sheet로 다는 방식)
- 모션레이아웃을 사용한다
- 리사이클러뷰의 스크롤을 활용해서, 최상단일때 뭔가 이벤트를 잡아서 처리한다
1번은 시도했는데, `STATE_EXPAND`, `peek_height` 제어가 까다로워서 해보다가 넘겼고, 모션레이아웃을 사용하는 방법은 최후의 보루로 남겨두기로 했다.
그렇게 세번째 방법을 사용했다.
# onScroll로 시도
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
// 여기서 스크롤 감지
}
})
recyclerview에는 콜백 중에 `addOnScrollListener`가 있어서 스크롤을 감지할 수 있다. , 처음 방식은 최상단에 닿았을 때를 기준으로 스크롤이 줄어들면 일정 값 이하일 때 뷰를 다시 만들어주는 형태였다. 최상단을 감지한 방식은 layoutManager의 첫번째 아이템 포지션이 0인 것으로 했다.
layoutManager.findFirstCompletelyVisibleItemPosition()
이걸 저 스크롤안에서 계속 실행되게 하면 최상단 감지가 가능하다.
이 방식은 문제가 있다. 스크롤하면서 애매하게 기준 값에 걸쳐서 위아래로 변하면 뷰가 막 사라졌다가 생겼다가 요동친다. 그래서 이 방법은 못써먹겠다고 생각했다.
그래서 pullRefresh 방식을 떠올렸고 그러다 찾은게 `edgeEffectFactory`다.
# `edgeEffectFactory`
pullRefresh같은 스크롤 땡김을 오버스크롤이라고 부르는 듯하다.
recyclerView.edgeEffectFactory = object : RecyclerView.EdgeEffectFactory() {
override fun createEdgeEffect(recyclerView: RecyclerView, direction: Int): EdgeEffect {
return object : EdgeEffect(recyclerView.context) {
override fun onPull(deltaDistance: Float) {
super.onPull(deltaDistance)
}
override fun onPull(deltaDistance: Float, displacement: Float) {
super.onPull(deltaDistance, displacement)
}
}
}
}
`createEdgeEffect`는 기본적으로 네 방향 모두 지원한다. onPull이 두개인데, API 21 기준으로 버전 분기처리를 해준 코드다.(아래가 더 최신)
deltaDistance는 오버스크롤한 거리를 나타낸다. displacement는 오버스크롤의 누적된 거리를 나타낸다. 이 두 차이는 극명하다. 오버스크롤을 해보면 순간 나타나고 사라지는데, displacement는 touch가 떨어지지않는한 누적거리를 갖고있기 때문에 좀 더 세밀한 제어가 가능하다는 차이점이 있다.
내가 onPull에서 처리한 로직은 아래와 같다.
private fun handlePull(direction: Int, deltaDistance: Float) {
when (direction) {
1 -> {
handlePullState++
}
}
if (handlePullState > 5) {
updateCalendar(Calendar.RESTORE)
handlePullState = 0
}
}
direction이 1이면 상단에서 일어나는 pull 이벤트다. 한 번 호출될 때 handlePullState라는 변수값을 증가시켜서 이게 5번 호출되면 달력 뷰를 복구해주도록 설계했다.
도움이 됐다면 댓글이나 공감 버튼 한 번씩 누르고 가주세요!
'Android 🖥️ > 삽질⛏️' 카테고리의 다른 글
Paging3 라이브러리 사용하기 (0) | 2024.07.30 |
---|---|
lifecycleScope와 viewLifecycleOwner.lifecycleScope (0) | 2024.07.27 |
ViewType을 나눠 RecyclerView를 구성하기(feat. SealedClass) (0) | 2024.07.23 |
Expandable FAB(Floating Action Button) 구현하기 - ListPopupWindow (0) | 2024.07.20 |
Tmap 대중교통 API + Navermap PathOverlay로 경로선 그리기 (0) | 2024.07.14 |