Skip to content

Instantly share code, notes, and snippets.

@charbgr
Forked from ZacSweers/OffsetsWithDirection.kt
Created August 17, 2017 12:54
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save charbgr/dbedf168c10209a58432a25f81a551d2 to your computer and use it in GitHub Desktop.
Save charbgr/dbedf168c10209a58432a25f81a551d2 to your computer and use it in GitHub Desktop.
Observable stream of AppBarLayout offsets + scroll direction
/*
* Here we want to get the appbar offset changes paired with the direction it's moving and
* using RxBinding's great `offsetChanges` API to make an rx Observable of this. The first
* part buffers two while skipping one at a time and emits "scroll direction" enums. Second
* part is just a simple map to pair the offset with the resolved scroll direction comparing
* to the previous offset. This gives us a nice stream of (offset, direction) emissions.
*
* Note that the filter() is important if you manipulate child views of the ABL. If any child
* view requests layout again, it will trigger an emission from the offset listener with the
* same value as before, potentially causing measure/layout/draw thrashing if your logic
* reacting to the offset changes *is* manipulating those child views (vicious cycle).
*/
RxAppBarLayout.offsetChanges(appBarLayout)
.buffer(2, 1) // Buffer in pairs to compare the previous, skip 1 at a time
.filter { it[1] != it[0] }
.map { Pair(it[1], ScrollDirection.resolve(it[1], it[0])) } // Map to a direction
.subscribe { (offset, direction) ->
// Profit
}
enum class ScrollDirection {
UP, DOWN;
companion object {
fun resolve(current: Int, prev: Int): ScrollDirection {
return if (current > prev) {
DOWN
} else {
UP
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment