I’m working on a Jetpack Compose app where I want a Text item in a LazyColumn become transparent as it scrolls under a semi-transparent TopAppBar. To achieve this, I’m using onGloballyPositioned to get the Text’s Y-coordinate and trigger an animation when it approaches the TopAppBar.
However, both positionInWindow() and positionInRoot() return the same Y-coordinate, which seems to include the status bar height. As a result, the animation starts too late — when the Text is fully under the TopAppBar instead of when its top edge touches the TopAppBar. My Scaffold uses statusBarsPadding() to handle system insets, but this doesn’t affect the coordinate system.
How to get the coordinates inside Composable window (not from the edge of screen) desirably without crutches like counting the size of statusBar?
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
ExampleTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
Demo(Modifier.padding(innerPadding))
}
}
}
}
}
@Composable
internal fun Demo(modifier: Modifier = Modifier) {
val density = LocalDensity.current
val topBarHeightPx = with(density) { 60.dp.toPx() }
var wineTitleOffset by remember { mutableStateOf(Offset.Zero) }
val nameFraction = ((topBarHeightPx - wineTitleOffset.y) / topBarHeightPx * 2).coerceIn(0f, 1f)
val textColor = lerp(0f, 1f, nameFraction)
Scaffold(
modifier = modifier,
contentWindowInsets = WindowInsets.systemBars,
topBar = {...}
) {
LazyColumn{
item { Spacer(modifier = Modifier.height(60.dp)) }
items(10) {
Text(text = "Hello, Peter")
}
item {
Layout(
content = {
Text(
"EXAMPLE TEXT",
fontWeight = FontWeight.Bold,
fontSize = 20.sp,
modifier = Modifier
.layoutId(WineName)
.wrapContentHeight(align = Alignment.CenterVertically)
// COUNTING THE COORDINATES:
.onGloballyPositioned { coordinates ->
val windowPos = coordinates.positionInWindow()
val rootPos = coordinates.positionInRoot()
Log.d("Position", "Window: $windowPos | Root: $rootPos")
val pos = coordinates.positionInRoot()
wineTitleOffset = Offset(pos.x, pos.y)
}
,
textAlign = TextAlign.Center,
color = Color.Black.copy(alpha = textColor)
)
}...
example of output:
Window: Offset(0.0, 196.0) | Root: Offset(0.0, 196.0)
Sorry, I cannot add a picture as I do not have enough reputation