【问题标题】:How to rotate a composable and add a progress listener to the rotation?如何旋转可组合并将进度侦听器添加到旋转中?
【发布时间】:2021-10-25 10:20:39
【问题描述】:

我正在尝试将基于视图的代码转换为 Compose。我有一个可组合的,它将图像(画家)作为参数并使用图像可组合显示它。我想要的是,每当参数值发生变化时,我的图像应该进行 360 度旋转,并且图像应该在角度约为 1 时发生变化。 180 度(即动画中途)

这是我制作的可组合。

@Composable
fun MyImage(displayImage: Painter) {
    Image(
        painter = displayImage,
        contentDescription = null,
        modifier = Modifier
            .size(36.dp)
            .clip(CircleShape)
    )
}

现在当displayImage 改变时,新图像立即显示,没有任何动画(显然)。如何实现所需的动画?

我尝试转换的代码如下所示:

fun onImageChange(imageRes: Int) {
    ObjectAnimator.ofFloat(imageView, View.ROTATION, 0f, 360f)
        .apply {
            addUpdateListener {
                if (animatedFraction == 0.5f) {
                    imageView.setImageResource(imageRes)
                }
            }
            start()
        }
}

【问题讨论】:

    标签: android kotlin android-animation android-jetpack-compose jetpack-compose-animation


    【解决方案1】:

    可以使用Animatable来完成。

    Compose 动画基于协程,因此您可以等待animateTo 挂起函数完成,更改图像并运行另一个动画。这是一个基本示例:

    var flag by remember { mutableStateOf(true) }
    val resourceId = remember(flag) { if (flag) R.drawable.profile else R.drawable.profile_inverted }
    val rotation = remember { Animatable(0f) }
    val scope = rememberCoroutineScope()
    
    Column(Modifier.padding(30.dp)) {
        Button(onClick = {
            scope.launch {
                rotation.animateTo(
                    targetValue = 180f,
                    animationSpec = tween(1000, easing = LinearEasing)
                )
                flag = !flag
                rotation.animateTo(
                    targetValue = 360f,
                    animationSpec = tween(1000, easing = LinearEasing)
                )
                rotation.snapTo(0f)
            }
        }) {
            Text("Rotate")
        }
        Image(
            painterResource(id = resourceId),
            contentDescription = null,
            modifier = Modifier
                .size(300.dp)
                .rotate(rotation.value)
        )
    }
    

    输出:

    如果您想为不断变化的图像制作动画,您必须将两张图像放在Box 中,并在它们旋转时使用另外一张Animatable 为它们的不透明度制作动画。

    【讨论】:

    • 感谢您的回答,让我尝试编码。但是在这里,您在同一个可组合物中使用了两种图像资源。我编写的 MyImage 可组合只接受一个图像(新图像),有没有办法记住旧值或者我必须更改函数定义并传递两个值?
    • @ArpitShukla 当然,你可以用remember 记住它。类似var actualImage by remember(inputImage) { mutableStateOf(inputImage) },然后在动画期间你可以做actualImage = tmpImage,如果你需要恢复它-actualImage = inputImage
    猜你喜欢
    • 2019-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-02
    • 2017-03-05
    • 1970-01-01
    • 2018-06-05
    • 1970-01-01
    相关资源
    最近更新 更多