У меня есть LinearProgressIndicator, который правильно показывает текущий прогресс. Теперь я хотел бы, чтобы прогресс был анимирован, и подумал, что с animateFloatAsState это будет очень просто. Ну, не уверен, что я не гроккнул, но с приведенным ниже кодом прогресс не анимируется, а сразу отображается в нужном месте.

@Composable
fun MyIndicator() {
    val progressAnimDuration = 1500
    val progressAnimation by animateFloatAsState(
        targetValue = 0.35f
        animationSpec = tween(durationMillis = progressAnimDuration, easing = FastOutSlowInEasing)
    )
     LinearProgressIndicator(
        progress = progressAnimation,
        ...
        modifier = Modifier           
           .fillMaxWidth()
           .clip(RoundedCornerShape(20.dp)). // Rounded edges
    )
}

Поэтому всякий раз, когда я показываю этот компонент на экране, я ожидаю, что прогресс будет анимирован до его правильного состояния. Но вместо этого прогресс не анимируется, а сразу отображается в правильном состоянии.

Что здесь не так? :)

1
Johan Paul 17 Сен 2021 в 13:00

2 ответа

Лучший ответ

У меня была аналогичная проблема, в моем случае я использовал LaunchedEffect для обновления прогресса с нуля до желаемого значения

@Composable
fun MyIndicator(indicatorProgress: Float) {
   var progress by remember { mutableStateOf(0f) }
    val progressAnimDuration = 1500
    val progressAnimation by animateFloatAsState(
        targetValue = indicatorProgress, 
        animationSpec = tween(durationMillis = progressAnimDuration, easing = FastOutSlowInEasing)
    )
    LinearProgressIndicator(
        modifier = Modifier
            .fillMaxWidth()
            .clip(RoundedCornerShape(20.dp)), // Rounded edges
        progress = progressAnimation
    )
    LaunchedEffect(indicatorProgress) {
        progress = indicatorProgress
    }
}
1
Dani Chuks 17 Сен 2021 в 11:50

Чтобы анимировать значение с помощью animateFloatAsState, вам нужно изменить целевое значение между перекомпозициями, например, следующим образом:

val progressAnimDuration = 1500
var progress by remember { mutableStateOf(0f) }
val progressAnimation by animateFloatAsState(
    targetValue = progress,
    animationSpec = tween(durationMillis = progressAnimDuration, easing = FastOutSlowInEasing)
)
LinearProgressIndicator(
    progress = progressAnimation,
)
Button(onClick = {
    progress += 0.1f
}) {

}

Другой вариант - использовать Animatable. В разных сценариях могут быть полезны оба варианта.

val progressAnimDuration = 1500
val progress = remember { Animatable(0f) }
LinearProgressIndicator(
    progress = progress.value,
)
val scope = rememberCoroutineScope()
Button(onClick = {
    scope.launch {
        progress.animateTo(
            progress.value + 0.1f,
            animationSpec = tween(
                durationMillis = progressAnimDuration,
                easing = FastOutSlowInEasing
            )
        )
    }
}) {

}

Дополнительные сведения об анимации см. В документации

0
Philip Dukhov 17 Сен 2021 в 10:14