Assigned
Status Update
Comments
ma...@google.com <ma...@google.com> #2
Hi, please share the stacktrace as the specifics are important.
ma...@google.com <ma...@google.com> #3
and a full repro if possible
va...@google.com <va...@google.com> #4
This snippet reproduces the issue:
@OptIn(ExperimentalMaterial3Api::class)
@Preview
@Composable
fun Repro() {
var isTwoLines by remember { mutableStateOf(false) }
LaunchedEffect(isTwoLines) {
delay(2000)
isTwoLines = !isTwoLines
}
val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
Scaffold(
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = {
MediumTopAppBar(
title = {
Text(
if (isTwoLines) "Medium\nTopAppBar" else "Medium TopAppBar",
)
},
scrollBehavior = scrollBehavior
)
},
) { innerPadding ->
LazyColumn(
contentPadding = innerPadding,
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
val list = (0..75).map { it.toString() }
items(count = list.size) {
Text(
text = "${scrollBehavior.state.heightOffsetLimit}",
style = MaterialTheme.typography.bodyLarge,
modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
)
}
}
}
}
As the size of the title changes, the heightOffsetLimit
changes the value.
Since TopAppBarState
is @Stable
, this should be guaranteed to be observable:
* 2) When a public property of the type changes, composition will be notified.
However, when scrolling, different items can show different values for the heightOffsetLimit
, which indicates that composition is not being notified when the heightOffsetLimit
changes because the items reading the heightOffsetLimit
are not recomposing, which breaks the @Stable
contract.
Description
Jetpack Compose version: CMP 1.8.0-dev1890
Material Library Version (M2, M3 or Both?): M3
Material Compose component used: androidx.compose.material3.TopAppBarState
Android Studio Build: #AI-242.23339.11.2422.12548333
Kotlin version: 2.1.0-Beta2
Steps to Reproduce or Code Sample to Reproduce:
It's obvious from looking at the line here , where here and here which re-assign the var.
heightOffsetLimit
is a var and assigned a static value, and the violationsThis re-assignment means that anyone using
heightOffsetLimit
in a composable will not be notified when it gets updated. This manifests for me as a crash during scrolling because it's expecting a non-zero height, but the specifics are not important.The state is marked here , so each publicly visible and mutable field needs to be snapshot aware.
@Stable
As a workaround, if one does
then it'll at least fix the crash on scroll, although you do miss out on the initial value and thus any placement relative to the app bar is broken until the user scrolls.
This was broken inhttps://android-review.googlesource.com/c/platform/frameworks/support/+/3123371
Stack trace (if applicable): N/A