Skip to content

Instantly share code, notes, and snippets.

@vrendina
Last active February 20, 2018 18:46
Show Gist options
  • Save vrendina/bd26e32876857f82728a0870b2d6849a to your computer and use it in GitHub Desktop.
Save vrendina/bd26e32876857f82728a0870b2d6849a to your computer and use it in GitHub Desktop.
RecyclerView Endless Scroll Listener
import android.support.v7.widget.GridLayoutManager
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import android.support.v7.widget.StaggeredGridLayoutManager
class EndlessScrollListener(private val layoutManager: RecyclerView.LayoutManager,
private val callback: EndlessScrollCallback) :
RecyclerView.OnScrollListener() {
companion object {
private const val VISIBLE_ITEM_THRESHOLD = 10
}
private val visibleThreshold: Int
private val lastLoadedPosition
get() = layoutManager.itemCount - 1
init {
visibleThreshold = when (layoutManager) {
is StaggeredGridLayoutManager -> VISIBLE_ITEM_THRESHOLD * layoutManager.spanCount
is GridLayoutManager -> VISIBLE_ITEM_THRESHOLD * layoutManager.spanCount
is LinearLayoutManager -> VISIBLE_ITEM_THRESHOLD
else -> throw IllegalArgumentException()
}
}
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
when {
isScrollingDown(dy) -> if (shouldLoadNext()) callback.loadNextPage()
isScrollingUp(dy) -> if (shouldLoadPrev()) callback.loadPreviousPage()
}
}
private fun isScrollingDown(dy: Int) = dy > 0
private fun isScrollingUp(dy: Int) = dy < 0
private fun shouldLoadNext() = getLastVisiblePosition() >= lastLoadedPosition - visibleThreshold
private fun shouldLoadPrev() = getFirstVisiblePosition() <= visibleThreshold
private fun getFirstVisiblePosition(): Int {
return when (layoutManager) {
is StaggeredGridLayoutManager -> layoutManager.findFirstVisibleItemPositions(null).min() ?: 0
is GridLayoutManager -> layoutManager.findFirstVisibleItemPosition()
is LinearLayoutManager -> layoutManager.findFirstVisibleItemPosition()
else -> throw IllegalArgumentException()
}
}
private fun getLastVisiblePosition(): Int {
return when (layoutManager) {
is StaggeredGridLayoutManager -> layoutManager.findLastVisibleItemPositions(null).max() ?: 0
is GridLayoutManager -> layoutManager.findLastVisibleItemPosition()
is LinearLayoutManager -> layoutManager.findLastVisibleItemPosition()
else -> throw IllegalArgumentException()
}
}
interface EndlessScrollCallback {
fun loadNextPage()
fun loadPreviousPage()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment