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
为了减少彩色动画的重新组合,我通常在DrawBehind中使用DrawRest,但如果我有一个图标怎么办?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?
但如果我有一个图标呢?在下面的例子中,重组计数工具中的重组次数约为11次,而draRect()将不会像我预期的那样工作,因为具有指定颜色的矩形将被简单地绘制在图标后面,但不会改变图标本身的颜色。在这种情况下,我如何才能减少重新组合的次数?
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.
你可以用Memory Painter(ImageVector)获得Painter,DrawScope有一个Painter的扩展函数。由于我们的动画绘制阶段,您将只有一次重组。
Also you can either set a fixed size or get painter size in dp with its intrinsic size which is size of drawable itself.
你也可以设定一个固定的尺寸,或者在DP中用它的固有尺寸,也就是可抽屉本身的尺寸来获得喷漆器尺寸。
@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
}
)
}
更多回答
I think you have dragged the state value to the drawing Phase of composable so It will only affect the drawing scope rather than Composable scope. Right?
我认为您已经将状态值拖到了Composable的绘制阶段,因此它只会影响绘制范围,而不会影响Composable范围。对吗?
That's right. Modifiers with lambda defer state reads to layout or drawing phase. Using Modifier.drawBehind only drawing phase is called during color change animation. Canvas is also a Spacer Modifier.drawBehind modifier that's why you can either this one or Canvas. developer.android.com/jetpack/compose/performance/…
没错。具有lambda状态的修改器将读取推迟到布局或绘图阶段。使用Modifier.Drawing在颜色更改动画期间只调用绘制阶段。Canvas也是Spacer Modifier.draBehind修改器,这就是为什么您可以选择这个修改器或Canvas修改器。Developer.android.com/jetpack/compose/performance/…
我是一名优秀的程序员,十分优秀!