본문 바로가기
안드로이드/코틀린

recyclerView 스크롤 이벤트 작성

by 나이아카 2021. 12. 29.
728x90

 jetpack이 나오고 난 후로 페이징 관련해서 paging이라는 친절한 친구를 제공하고 있습니다. 하지만 아직까지도 여러가지 이유로 인해 리사이클러뷰의 스크롤링을 조절해야줘야 하는 상황이 생기죠.

 이를 사용하기 위해 간단하게 작성한 코드를 까먹을 때 마다 보러 오기 위해 남겨둡니다. 사실 리사이클러뷰 자체에 대해서 잘 모르는 경우에는 이 코드를 보고 단번에 이해하지 못하실 가능성이 높을지도...?


/**
 * 스크롤 아래로 퍼센트 계산
 * @return %
 */
fun scrollPercent(recyclerView: RecyclerView): Double {
    return (recyclerView.computeVerticalScrollOffset() * 1.0 / (recyclerView.computeVerticalScrollRange() - recyclerView.computeVerticalScrollExtent())) * 100.0
}

fun RecyclerView.scrollPercent() : Double {
    return (this.computeVerticalScrollOffset() * 1.0 / (this.computeVerticalScrollRange() - this.computeVerticalScrollExtent())) * 100.0
}

 

 먼저 리사이클러뷰의 스크롤이 끝까지 내려왔는지를 판단하기 위해 퍼센트 계산 메소드를 작성해줍니다. 저는 IndefendentFunction이라는 코틀린 파일을 만들어 특정 클래스에 종속되지 않는 메소드로 사용하고 있습니다.

 간단하게 하나씩 살펴보자면 먼저 computeVerticalScrollOffset() 메소드는 현재 리사이클러뷰의 지나간 영역을 알려주는 메소드입니다. computeVerticalScrollRange() 메소드는 현재 리사이클러뷰에서 할당된 값(리사이클러뷰를 스크롤할 수 있는 총 값)을 반환해주는 메소드입니다. 마지막으로 computeVerticalScrollExtent() 메소드는 현재 휴대폰으로 보여지고 있는 리사이클러뷰의 영역을 의미합니다. 

offset + extend = range 

 리사이클러뷰는 위와 같은 공식을 따르고 있습니다. 이를 이용하면 offset = range - extend임을 알 수 있고, 이를 좀 퍼센트로 나타내기 위해 offset/(range - extend) = 1 로 만든 후, 양 변에 100을 곱해 100%를 만들어주는 것입니다.

 저는 아래 코드를 Fragment의 onViewCreated에 작성하였습니다.

binding.myRecyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
    override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
    super.onScrolled(recyclerView, dx, dy)
        if(scrollPercent(binding.myRecyclerView) >= 100) {
            //dataLoading()
        }
    }
})

 

 위에서 구한 스크롤 퍼센트를 fragment(activity) 내부 recyclerView의 addOnScrollListener에서 사용할 수 있게 하는 코드입니다. 이 코드는 fragment 및 activity에 붙여주면 됩니다.

 onScrolled는 리사이클러뷰가 스크롤링될 때 발생하는 콜백 메소드로 스크롤링 될 때마다 스크롤의 퍼센트를 구해 이 퍼센트가 100퍼가 되었을 때(맨 아래에 도달했을 때) 데이터를 불러오는 방식으로 진행하는 것입니다.


 이 2개의 코드를 이용하면, 간단하게 끝까지 스크롤했을 때 추가적인 데이터를 불러오는 코드를 작성할 수 있습니다. dataLoading 부분은 각 프로젝트마다 서버 및 내부 저장소에서 불러오는 데이터가 다를 것이기 때문에 기존에 사용하던 방식으로 사용할 수 있을 것입니다.

 물론 내부저장소에서 데이터를 불러올 때는 페이징 라이브러리를 이용하는 것이 훨씬 효과적이지만, 그것보다는 이런식으로 사용하는 것이 훨씬 효과적이기는 합니다. 하지만 회사나 개인 프로젝트를 진행할 때 대부분은 서버에서 데이터를 불러와야 하고, 모든 데이터를 한 번에 불러오게 되면 낭비가 심해져서 데이터를 페이지별로 분류해서 불러오는 경우가 많습니다. 이를 위해 이 코드는 계속 사용되리라 생각합니다.(물론 안드로이드 특성상 언제 버그가 발견되어 이 코드를 못쓰게 될 진 모르겠습니다. 혹은 새로운 코드가 발견되서 비효율적이 되거나...)

반응형

댓글