Seri
09/18/2024, 8:50 PMSean Proctor
09/18/2024, 9:55 PMSean Proctor
09/18/2024, 9:55 PM@Composable
fun NestedScrollOffsetBox(
toolbarHeight: Dp,
modifier: Modifier = Modifier,
content: @Composable NestedBoxScope.() -> Unit,
) {
// here we use LazyColumn that has build-in nested scroll, but we want to act like a
// parent for this LazyColumn and participate in its nested scroll.
// Let's make a collapsing toolbar for LazyColumn
val toolbarHeightPx = with(LocalDensity.current) { toolbarHeight.roundToPx().toFloat() }
// our offset to collapse toolbar
val toolbarOffsetHeightPx = remember { mutableStateOf(0f) }
// now, let's create connection to the nested scroll system and listen to the scroll
// happening inside child LazyColumn
val nestedScrollConnection = remember {
object : NestedScrollConnection {
override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
// try to consume before LazyColumn to collapse toolbar if needed, hence pre-scroll
val delta = available.y
val newOffset = toolbarOffsetHeightPx.value + delta
toolbarOffsetHeightPx.value = newOffset.coerceIn(-toolbarHeightPx, 0f)
// here's the catch: let's pretend we consumed 0 in any case, since we want
// LazyColumn to scroll anyway for good UX
// We're basically watching scroll without taking it
return Offset.Zero
}
}
}
Box(modifier.clipToBounds().fillMaxSize().nestedScroll(nestedScrollConnection)) {
with(NestedBoxScopeImpl(this, toolbarOffsetHeightPx.value)) {
content()
}
}
}
interface NestedBoxScope : BoxScope {
fun Density.getOffset(): IntOffset
}
class NestedBoxScopeImpl(
private val boxScope: BoxScope,
private val offsetPx: Float,
) : NestedBoxScope {
override fun Modifier.align(alignment: Alignment): Modifier {
return with(boxScope) { this@align.align(alignment) }
}
override fun Modifier.matchParentSize(): Modifier {
return with(boxScope) { this@matchParentSize.matchParentSize() }
}
override fun Density.getOffset(): IntOffset {
return IntOffset(x = 0, y = offsetPx.roundToInt())
}
}
Sean Proctor
09/18/2024, 9:58 PMval height = 72.dp
NestedScrollOffsetBox(height) {
List()
Header(
modifier = Modifier
.height(height)
)
}
Seri
09/18/2024, 9:59 PMExitUntilCollapsedScrollBehavior
and in this article on nested scrolling. Adapting these seems like a good approach!
https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/[…]rScrollBehavior&ss=androidx%2Fplatform%2Fframeworks%2Fsupport
https://medium.com/androiddevelopers/understanding-nested-scrolling-in-jetpack-compose-eb57c1ea0af0