Hammad Qaiser
09/02/2025, 9:29 AMNestedScrollConnection
. More in đź§µHammad Qaiser
09/02/2025, 9:29 AMTopAppBarDefaults.exitUntilCollapsedScrollBehavior
in a Scaffold
and LazyColumn
.
The issue: when scrolling, the top bar collapses first, and only after that does the list start scrolling, leaving an unexpected “gap.”
I expected the Scaffold
to handle this automatically.
Since I need a fully custom layout (not the built-in Material TopAppBar), why does this gap appear, and what’s the proper way to handle it?
Code:
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SampleScreen() {
val maxScrollOffsetDp = 100.dp // height of the top app bar that should be offset
val maxScrollOffsetF = with(LocalDensity.current) {
maxScrollOffsetDp.toPx()
}
val topBarState = TopAppBarDefaults.exitUntilCollapsedScrollBehavior(
state = rememberTopAppBarState(
initialHeightOffsetLimit = -maxScrollOffsetF
)
)
Scaffold(
containerColor = Color.Blue,
topBar = {
SampleTopBar(
scrollOffset = topBarState.state.heightOffset,
progress = topBarState.state.collapsedFraction
)
},
modifier = Modifier.nestedScroll(topBarState.nestedScrollConnection)
) { innerPadding ->
LazyColumn(
contentPadding = innerPadding,
) {
items(20) { item ->
Text(
text = "item no: $item",
modifier = Modifier
.fillMaxWidth()
.height(60.dp)
.padding(vertical = 2.dp)
.background(color = Color.LightGray)
)
}
}
}
}
@Composable
fun SampleTopBar(
scrollOffset: Float,
progress: Float
) {
Column(
modifier = Modifier
.offset { IntOffset(0, scrollOffset.toInt()) }
.background(Color.Magenta)
.statusBarsPadding()
.fillMaxWidth()
.padding(vertical = 10.dp),
) {
Text(
text = "I should fade out",
modifier = Modifier
.alpha(1f - progress)
.background(Color.Yellow)
.padding(top = 40.dp)
.height(40.dp)
.fillMaxWidth()
)
Text(
text = "I should stick to the top",
modifier = Modifier
.padding(top = 20.dp)
.background(Color.Green)
.fillMaxWidth()
.height(40.dp)
)
}
}
Hammad Qaiser
09/03/2025, 6:35 AM