In the XML-based UI, FAB had a field to override the custom scroll behavior. Since there is no such parameter in the function in Compose FAB implementation, it became a little unclear how to implement the hide on scroll behavior.
I use Scaffold with the nestedScroll
modifier in order for my СollapsingAppBar to work. I assumed at first that it was necessary to create an object inherited from the NestedScrollConnection
interface. And also connect it with the nestedScroll
modifier to Scaffold. But unfortunately, as I understand it, it is impossible to connect several scrollBehavior
objects to one Scaffold at once.
val scrollBehavior = TopAppBarScrollBehavior()
val scrollBehavior1 = FloatingActionButtonScrollBehavior()
Scaffold(
modifier = Modifier
.nestedScroll(scrollBehavior.nestedScrollConnection)
//this one won't work
.nestedScroll(scrollBehavior1.nestedScrollConnection)
...
If someone is interested in how to implement this behavior, I found this solution:
@Composable
fun AnimatedFloatingActionButton(
...
listState: LazyListState
) {
AnimatedVisibility(
visible = listState.isScrollingUp().value,
enter = //TODO: your enter animation,
exit = //TODO: your exit animation
) {
FloatingActionButton(
...
)
}
}
You only need to create a LazyListState
inside your Composable parent, and pass it inside the AnimatedFloatingActionButton
. And also define an extension function for LazyListState
.
@Composable
fun LazyListState.isScrollingUp(): State<Boolean> {
return produceState(initialValue = true) {
var lastIndex = 0
var lastScroll = Int.MAX_VALUE
snapshotFlow {
firstVisibleItemIndex to firstVisibleItemScrollOffset
}.collect { (currentIndex, currentScroll) ->
if (currentIndex != lastIndex || currentScroll != lastScroll) {
value = currentIndex < lastIndex ||
(currentIndex == lastIndex && currentScroll < lastScroll)
lastIndex = currentIndex
lastScroll = currentScroll
}
}
}
}