smoothScrollBy는 스크롤을 부드럽게 이동시키는 데 사용된다. smoothScrollBy 메서드는 일정한 속도와 시간 간격으로 스크롤을 이동시켜 부드러운 스크롤 경험을 제공한다.
캘린더를 구현할 때 일자를 6주 * 7일로 총 42개의 날짜를 표시하게 했다. 그러다 보니 현재 보여지는 달을 제외하고도 이전 달 끝의 일자 몇 개와 다음 달 시작하는 일자 몇 개가 한 화면에 같이 표시되고 있다.
현재 보여지는 달에 해당하는 일자가 아닌 부분을 클릭하면 화면을 스크롤 하여 클릭한 일자에 해당하는 달을 보여주고 싶었는데 그러려면 리사이클러뷰의 아이템을 클릭할 때 화면이 자동으로 스크롤 되어야 하므로 해당 부분을 smoothScrollBy을 사용하여 구현하였다.
// DayListAdapter
binding.root.setOnClickListener {
val isPreviousMonth = date.monthValue < tempMonth
val isNextMonth = date.monthValue > tempMonth
if (isPreviousMonth) {
onMonthChange(true)
} else if (isNextMonth) {
onMonthChange(false)
} else {
onItemClick(adapterPosition, date)
}
}
binding.root.setOnClickListener는 일자를 화면에 표시하는 DayListAdapter에서 일자를 클릭할 때 호출되는 이벤트 리스너이다.
1. 클릭된 일자가 월의 이전 월에 속하는지, 다음 월에 속하는지를 확인한다.
2. 클릭 된 날짜가 현재 월의 이전 월에 속한다면 onMonthChange(true)를 호출하여 이전 월로 스크롤 할 것임을 알린다.
3. 클릭 된 날짜가 현재 월의 다음 월에 속한다면 onMonthChange(false)를 호출하여 다음 월로 스크롤 할 것임을 알린다.
4. 현재 월의 날짜인 경우에는 onItemClick(adapterPosition, date)를 호출하여 해당 날짜에 대한 작업을 한다.
// MonthListAdapter
dayListAdapter = DayListAdapter(tempMonth, dayList, uiState, onItemClick = { _, date ->
onDayItemClick(date)
}, onMonthChange = { isPreviousMonth ->
onMonthScroll(isPreviousMonth)
})
MonthListAdapter는 캘린더에서 월을 표시하는 리사이클러뷰 어댑터이다.
onMonthChange는 DayListAdapter에서 이전 또는 다음 월에 해당하는 날짜를 클릭했을 때 호출되는 콜백 함수이다.
MonthListAdapter의 onMonthScroll 콜백은 프래그먼트에서 사용할 수 있으며, 이를 통해 프래그먼트는 이벤트에 대한 작업을 처리할 수 있다.
// CalendarFragment
private val scrollAmount: Int by lazy {
resources.displayMetrics.widthPixels
}
private fun setupMonthList(uiState: List<ScheduleModel>) {
val monthListManager = LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false)
val monthListAdapter = MonthListAdapter(::onDayItemClick, uiState) { isPreviousMonth ->
if (isPreviousMonth) {
binding.rcCalendar.smoothScrollBy(-scrollAmount, 0)
} else {
binding.rcCalendar.smoothScrollBy(scrollAmount, 0)
}
}
with(binding.rcCalendar) {
layoutManager = monthListManager
adapter = monthListAdapter
scrollToPosition(Int.MAX_VALUE / 2)
}
}
scrollAmount는 화면의 너비를 픽셀로 나타내는 변수로 캘린더 리사이클러뷰의 스크롤에 사용된다.
resources.displayMetrics.widthPixels으로 설정함으로써 화면의 너비에 따라 스크롤량을 동적으로 조절할 수 있다.
⚡️ 처음에는 resources.displayMetrics.widthPixels / 2로 설정하여 초기 스크롤 위치를 화면의 중앙에 놓으려고 했었다. 하지만 화면 너비의 절반만큼 스크롤을 설정했기에 스크롤이 되다가 다시 이전 화면으로 돌아오는 문제가 있었다. 스크롤 위치는 중요하지 않을 것 같아 resources.displayMetrics.widthPixels로 설정하여 화면의 전체 너비에 따라 스크롤을 조절했더니 원하는 동작을 얻을 수 있었다.
isPreviousMonth가 true 일 때는 이전 월로 스크롤해야 하므로, -scrollAmount만큼 스크롤 하여 왼쪽으로 스크롤 하는 효과를 준다.
isPreviousMonth가 false일 때는 다음 월로 스크롤해야 하므로, scrollAmount만큼 스크롤 하여 오른쪽으로 스크롤 하는 효과를 준다.