Как повернуть составной объект и добавить в ротацию прослушиватель прогресса?

Я пытаюсь преобразовать свой код, основанный на представлении, в Compose. У меня есть составной объект, который принимает изображение (Painter) в качестве аргумента и отображает его с помощью компонента Image composable. Я хочу, чтобы всякий раз, когда значение аргумента изменяется, мое изображение должно вращаться на 360 градусов, а изображение должно изменяться, пока угол составляет прибл. 180 градусов (т. Е. В середине анимации)

Это составной элемент, который я сделал.

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

Прямо сейчас, когда изменяется, новое изображение отображается сразу без какой-либо анимации (очевидно). Как добиться желаемой анимации?

Код, который я пытаюсь преобразовать, выглядит так:

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

1 ответ

Это можно сделать с помощью .

Компоновка анимации основана на сопрограммах, поэтому вы можете дождаться 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.