To reduce color animation recompositions, I usually use drawRest
in drawBehind
, but what if I have an icon?
https://developer.android.com/jetpack/compose/animation/quick-guide#animate-background
I often see examples like:
modifier = Modifier.drawBehind {
drawRect(animatedColor)
}
But what if I have an icon?
In the example below, the number of recompositions will be about 11 in Recomposition Counts Tool, and drawRect()
will won't work as I expect, because a rectangle with the specified color will simply be drawn behind the icon, but will not change the color of the icon itself. How can I reduce the number of recompositions in this situation?
val isClicked = remember {
mutableStateOf(false)
}
val color = animateColorAsState(targetValue = if (isClicked.value) Color.White else Color.Blue)
Icon(
modifier = Modifier.clickable {
isClicked.value = !isClicked.value
},
imageVector = Icons.Outlined.Home,
contentDescription = null,
tint = color.value,
)
You can get painter with rememberPainter(imageVector) and DrawScope has an extension function for painter. Since we animate in drawing phase you will only have one recomposition.
Also you can either set a fixed size or get painter size in dp with its intrinsic size which is size of drawable itself.
@Preview
@Composable
private fun ImageVectorAnimationSample() {
val isClicked = remember {
mutableStateOf(false)
}
val color by animateColorAsState(
targetValue = if (isClicked.value) Color.White else Color.Blue,
animationSpec = tween(durationMillis = 2000),
label = "tint"
)
val painter = rememberVectorPainter(Icons.Outlined.Home)
val dpSize = with(LocalDensity.current) {
painter.intrinsicSize.toDpSize()
}
SideEffect {
println("Composing...")
}
Box(
modifier = Modifier
// .size(dpSize)
.size(100.dp)
.drawBehind {
with(painter) {
draw(size, colorFilter = ColorFilter.tint(color))
}
}
.clickable {
isClicked.value = !isClicked.value
}
)
}