https://kotlinlang.org logo
#compose
Title
# compose
t

Tobias Gronbach

03/15/2022, 1:35 PM
Hi! I have a LazyColumn and want to change the screen-background-color to that of the item-background at the center-position. It's working fine I'm not sure if I do the calculations at the right place because as soon as I add those calculations I'm triggering infinite recomposition thats why I think I do something wrong. Code-Example in Thread.
Copy code
setContent {
 	val listState = rememberLazyListState()
	val viewPortCenter =  ((listState.layoutInfo.viewportEndOffset - listState.layoutInfo.viewportStartOffset) / 2)  // <- as soon as I add this line infinite recomposition is triggered

	....
}
a

Adam Powell

03/15/2022, 1:39 PM
You've asked to recompose that content root performing that calculation any time those inputs change so yes, that's likely to result in some recomposition loops. Try performing that calculation in a
derivedStateOf {}
and ensure you only access that derived state object at drawing time, e.g. in a
Modifier.drawBehind
or
Modifier.graphicsLayer {}
block
t

Tobias Gronbach

03/15/2022, 3:39 PM
Hi Adam, thank you so much for your thoughts! Still not getting it. Version 1 (working) but infinite recomposition:
Copy code
val listState = rememberLazyListState()
val viewPortCenter = ((listState.layoutInfo.viewportEndOffset - listState.layoutInfo.viewportStartOffset) / 2)
val centerItem = listState.layoutInfo.visibleItemsInfo.find { it.offset < viewPortCenter.value && (it.offset + it.size) > viewPortCenter.value }
val centeredBait = baits.find { it.adviceId == centerItem?.key } // I use adviceId as key in lazyColumn
var backgroundColorRes by remember { mutableStateOf(R.color.white) }

LaunchedEffect(centeredBait) {
    backgroundColorRes = centeredBait?.adviceType?.colorRes() ?: R.color.white
}
Version 2 (nothing happens at all):
Copy code
val viewPortCenter = derivedStateOf {
        ((listState.layoutInfo.viewportEndOffset - listState.layoutInfo.viewportStartOffset) / 2)
}

val centerItem by derivedStateOf {
         listState.layoutInfo.visibleItemsInfo.find { it.offset < viewPortCenter.value && (it.offset + it.size) > viewPortCenter.value }
}

val centeredBait by derivedStateOf {
        baits.find { it.adviceId == centerItem?.key }
}

LaunchedEffect(centeredBait) {
      backgroundColorRes = centeredBait?.adviceType?.colorRes() ?: R.color.white
}
As you can see I'm changing the backgroundColor in LaunchedEffect and set it as background-color to my composable. I'm afraid maybe it's the wrong approach. I'm still getting used to compose.
I got it working meanwhile, in case anyone is interested:
Copy code
val backgroundColorRes by remember {
                    derivedStateOf {
                        val viewPortCenter =
                            ((listState.layoutInfo.viewportEndOffset - listState.layoutInfo.viewportStartOffset) / 2)
                        val centerItem =
                            listState.layoutInfo.visibleItemsInfo.find { it.offset < viewPortCenter && (it.offset + it.size) > viewPortCenter }
                        val centeredBait = screenState.adviceBaits.find { bait -> bait.adviceId == centerItem?.key }
                        centeredBait?.adviceType?.colorRes() ?: R.color.white
                    }
                }
                
                val animateColor by animateColorAsState(colorResource(backgroundColorRes), animationSpec = tween(2000))
2 Views