代码之家  ›  专栏  ›  技术社区  ›  Danila Shabanov

如何减少Jetpack Compose中可设置动画的轮廓图标颜色的重新组合次数?

  •  0
  • Danila Shabanov  · 技术社区  · 2 年前

    为了减少彩色动画的重新合成,我通常使用 drawRest 在里面 drawBehind ,但是如果我有一个图标呢? https://developer.android.com/jetpack/compose/animation/quick-guide#animate-background

    我经常看到这样的例子:

    modifier = Modifier.drawBehind {
            drawRect(animatedColor)
        }
    

    但如果我有一个图标呢? 在下面的示例中,“重新计算计数工具”中的重新计算次数约为11次,并且 drawRect() 将不会像我预期的那样工作,因为具有指定颜色的矩形将简单地绘制在图标后面,但不会改变图标本身的颜色。在这种情况下,我如何才能减少报酬的数量?

    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,
    )
    
    1 回复  |  直到 2 年前
        1
  •  0
  •   Thracian    2 年前

    您可以使用rememberPainter(imageVector)获取painter,DrawScope具有painter的扩展功能。由于我们在绘制阶段设置了动画,您将只有一次重新组合。

    此外,您可以设置一个固定的大小,也可以在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
                }
        )
    }