Giovanni Marques
07/23/2024, 1:16 PMGiovanni Marques
07/23/2024, 1:18 PMLazyListState
Skaldebane
07/23/2024, 2:49 PMGiovanni Marques
07/23/2024, 2:58 PM@Composable
fun ColumnWithFab(
modifier: Modifier = Modifier,
scrollState: ScrollState = rememberScrollState(),
content: @Composable ColumnScope.() -> Unit
) {
var previousScrollOffset by remember { mutableIntStateOf(scrollState.value) }
var wasScrollingUp by remember { mutableStateOf(true) }
val isScrollingUp by remember {
derivedStateOf {
when {
abs(scrollState.value - previousScrollOffset) > SCROLL_OFFSET_THRESHOLD -> scrollState.value < previousScrollOffset
else -> null
}?.also {
previousScrollOffset = scrollState.value
wasScrollingUp = it
} ?: wasScrollingUp
}
}
Box(modifier) {
Column(
content = content,
modifier = Modifier
.verticalScroll(state = scrollState),
)
Fab(
showText = isScrollingUp,
modifier = Modifier
.align(Alignment.BottomEnd)
.padding(CanvasTheme.dimens.normal75),
)
}
}
@Composable
fun Fab(
modifier: Modifier = Modifier,
showText: Boolean,
) {
FloatingActionButton(
onClick = { },
shape = CircleShape,
backgroundColor = Color.Cyan,
modifier = modifier,
) {
Row(verticalAlignment = CenterVertically, modifier = Modifier.padding(horizontal = CanvasTheme.dimens.normal100)) {
Icon(Icons.Filled.Add, contentDescription = null)
AnimatedVisibility(showText) {
Text(text = "Expanded")
}
}
}
}
Every time I scroll the isScrollingUp
is recalculated and updated correctly, but if I extract the code that does the calculation to a separate method it doesn’t work:Giovanni Marques
07/23/2024, 2:59 PM@Composable
fun ColumnWithFab(
modifier: Modifier = Modifier,
scrollState: ScrollState = rememberScrollState(),
content: @Composable ColumnScope.() -> Unit
) {
Box(modifier) {
Column(
content = content,
modifier = Modifier
.verticalScroll(state = scrollState),
)
Fab(
showText = scrollState.isScrollingUp(),
modifier = Modifier
.align(Alignment.BottomEnd)
.padding(CanvasTheme.dimens.normal75),
)
}
}
@Composable
private fun ScrollState.isScrollingUp(): Boolean {
var wasScrollingUp by remember(this) { mutableStateOf(true) }
var previousScrollOffset by remember(this) { mutableIntStateOf(value) }
return remember(this) {
derivedStateOf {
when {
abs(value - previousScrollOffset) > SCROLL_OFFSET_THRESHOLD -> value < previousScrollOffset
else -> null
}?.also {
previousScrollOffset = value
wasScrollingUp = it
} ?: wasScrollingUp
}.value
}
}
@Composable
fun Fab(
modifier: Modifier = Modifier,
showText: Boolean,
) {
FloatingActionButton(
onClick = { },
shape = CircleShape,
backgroundColor = Color.Cyan,
modifier = modifier,
) {
Row(verticalAlignment = CenterVertically, modifier = Modifier.padding(horizontal = CanvasTheme.dimens.normal100)) {
Icon(Icons.Filled.Add, contentDescription = null)
AnimatedVisibility(showText) {
Text(text = "Expanded")
}
}
}
}
Giovanni Marques
07/23/2024, 2:59 PMisScrollingUp()
is called only once. Even though the scroll state is read in the isScrollingUp()
it doesn’t recompose when the scroll state changes. (edited)