diff --git a/flowbinding-recyclerview/README.md b/flowbinding-recyclerview/README.md index 527f8ee2c..f380d59ef 100644 --- a/flowbinding-recyclerview/README.md +++ b/flowbinding-recyclerview/README.md @@ -20,4 +20,6 @@ fun RecyclerView.childAttachStateChangeEvents(): Flow Boolean = { true }): Flow fun RecyclerView.scrollEvents(): Flow fun RecyclerView.scrollStateChanges(): Flow +fun RecyclerView.loadMoreFlowVertically(): Flow +fun RecyclerView.loadMoreFlowHorizontally(): Flow ``` diff --git a/flowbinding-recyclerview/src/main/java/reactivecircus/flowbinding/recyclerview/RecyclerViewLoadMoreFlow.kt b/flowbinding-recyclerview/src/main/java/reactivecircus/flowbinding/recyclerview/RecyclerViewLoadMoreFlow.kt new file mode 100644 index 000000000..0ed05263b --- /dev/null +++ b/flowbinding-recyclerview/src/main/java/reactivecircus/flowbinding/recyclerview/RecyclerViewLoadMoreFlow.kt @@ -0,0 +1,60 @@ +package reactivecircus.flowbinding.recyclerview + +import androidx.annotation.CheckResult +import androidx.recyclerview.widget.RecyclerView +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.callbackFlow +import kotlinx.coroutines.flow.conflate +import reactivecircus.flowbinding.common.checkMainThread + +/** + * Create a [Flow] of scroll events on the [RecyclerView] instance. + * + * Note: create a extension for loading more in different directions + * + * Example of usage: + * + * ``` + * recyclerView.loadMoreFlowVertically() + * .onEach { loadMore -> + * // handle data changed + * } + * .launchIn(uiScope) + * ``` + */ +@CheckResult +@OptIn(ExperimentalCoroutinesApi::class) +public fun RecyclerView.loadMoreFlowVertically(): Flow = callbackFlow { + checkMainThread() + val listener = object : RecyclerView.OnScrollListener() { + override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { + if (!recyclerView.canScrollVertically(1) && newState == RecyclerView.SCROLL_STATE_IDLE) { + trySend(true) + } else { + trySend(false) + } + } + } + addOnScrollListener(listener) + awaitClose { removeOnScrollListener(listener) } +}.conflate() + + +@CheckResult +@OptIn(ExperimentalCoroutinesApi::class) +public fun RecyclerView.loadMoreFlowHorizontally(): Flow = callbackFlow { + checkMainThread() + val listener = object : RecyclerView.OnScrollListener() { + override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { + if (!recyclerView.canScrollHorizontally(1) && newState == RecyclerView.SCROLL_STATE_IDLE) { + trySend(true) + } else { + trySend(false) + } + } + } + addOnScrollListener(listener) + awaitClose { removeOnScrollListener(listener) } +}.conflate() \ No newline at end of file