[Android / Kotlin] RecyclerView smoothScrollBy

Subeen·2024년 3월 19일
0

Android

목록 보기
69/73

smoothScrollBy

smoothScrollBy는 스크롤을 부드럽게 이동시키는 데 사용된다. smoothScrollBy 메서드는 일정한 속도와 시간 간격으로 스크롤을 이동시켜 부드러운 스크롤 경험을 제공한다.

  • smoothScrollBy의 매개변수
    • dx : 가로 방향으로 스크롤 할 픽셀 수로 오른쪽으로 스크롤을 하려면 양수 값, 왼쪽으로 스크롤을 하려면 음수 값을 전달한다.
    • dy : 세로 방향으로 스크롤 할 픽셀 수로 아래쪽으로 스크롤을 하려면 양수 값, 위쪽으로 스크롤을 하려면 음수 값을 전달한다.

캘린더를 구현할 때 일자를 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는 캘린더에서 월을 표시하는 리사이클러뷰 어댑터이다.
onMonthChangeDayListAdapter에서 이전 또는 다음 월에 해당하는 날짜를 클릭했을 때 호출되는 콜백 함수이다.
MonthListAdapteronMonthScroll 콜백은 프래그먼트에서 사용할 수 있으며, 이를 통해 프래그먼트는 이벤트에 대한 작업을 처리할 수 있다.

 	// 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만큼 스크롤 하여 오른쪽으로 스크롤 하는 효과를 준다.

profile
개발 공부 기록 🌱

0개의 댓글