Настройка анимации

Многие API для анимации обычно принимают параметры для настройки их поведения.

Настройте анимацию с помощью параметра AnimationSpec

Большинство API для анимации позволяют разработчикам настраивать параметры анимации с помощью необязательного параметра AnimationSpec .

val alpha: Float by animateFloatAsState(
    targetValue = if (enabled) 1f else 0.5f,
    // Configure the animation duration and easing.
    animationSpec = tween(durationMillis = 300, easing = FastOutSlowInEasing),
    label = "alpha"
)

Существуют различные типы AnimationSpec для создания разных видов анимации.

Создавайте анимацию, основанную на физических принципах, с помощью spring

spring создает анимацию, основанную на физических принципах, между начальным и конечным значениями. Она принимает 2 параметра: dampingRatio и stiffness .

dampingRatio определяет, насколько упругой должна быть пружина. Значение по умолчанию — Spring.DampingRatioNoBouncy .

Рисунок 1. Настройка различных коэффициентов демпфирования пружины.

stiffness определяет, с какой скоростью пружина должна двигаться к конечному значению. Значение по умолчанию — Spring.StiffnessMedium .

Рисунок 2. Настройка различной жесткости пружины.

val value by animateFloatAsState(
    targetValue = 1f,
    animationSpec = spring(
        dampingRatio = Spring.DampingRatioHighBouncy,
        stiffness = Spring.StiffnessMedium
    ),
    label = "spring spec"
)

spring обрабатывает прерывания более плавно, чем типы AnimationSpec основанные на продолжительности, поскольку гарантирует непрерывность скорости при изменении целевого значения во время анимации. spring используется в качестве AnimationSpec по умолчанию многими API анимации, такими как animate*AsState и updateTransition .

Например, если мы применим конфигурацию spring к следующей анимации, которая запускается касанием пользователя, то при прерывании анимации в процессе её выполнения вы увидите, что использование tween не обеспечивает такой же плавной реакции, как использование spring .

Рисунок 3. Установка параметров анимации tween и spring и ее прерывание.

Анимируйте переходы между начальными и конечными значениями с помощью кривой сглаживания tween анимации.

Функция tween анимирует переход между начальным и конечным значениями в течение заданного durationMillis с помощью кривой сглаживания. Слово tween является сокращением от between (между), поскольку анимация происходит между двумя значениями.

Также можно указать delayMillis , чтобы отложить начало анимации.

val value by animateFloatAsState(
    targetValue = 1f,
    animationSpec = tween(
        durationMillis = 300,
        delayMillis = 50,
        easing = LinearOutSlowInEasing
    ),
    label = "tween delay"
)

Дополнительную информацию см. в разделе «Упрощение» .

Анимируйте до определенных значений в определенные моменты времени с помощью keyframes

Анимация keyframes строится на основе значений, заданных в разные моменты времени в течение анимации. В любой момент времени значение анимации будет интерполировано между значениями двух ключевых кадров. Для каждого из этих ключевых кадров можно указать параметр "Easing" для определения кривой интерполяции.

Указывать значения в момент времени 0 мс и в момент продолжительности анимации можно по желанию. Если эти значения не указаны, по умолчанию используются начальное и конечное значения анимации соответственно.

val value by animateFloatAsState(
    targetValue = 1f,
    animationSpec = keyframes {
        durationMillis = 375
        0.0f at 0 using LinearOutSlowInEasing // for 0-15 ms
        0.2f at 15 using FastOutLinearInEasing // for 15-75 ms
        0.4f at 75 // ms
        0.4f at 225 // ms
    },
    label = "keyframe"
)

Плавная анимация между ключевыми кадрами с помощью keyframesWithSplines

Для создания анимации, плавно переходящей от одного значения к другому по кривой, можно использовать keyframesWithSplines вместо спецификаций анимации keyframes .

val offset by animateOffsetAsState(
    targetValue = Offset(300f, 300f),
    animationSpec = keyframesWithSpline {
        durationMillis = 6000
        Offset(0f, 0f) at 0
        Offset(150f, 200f) atFraction 0.5f
        Offset(0f, 100f) atFraction 0.7f
    }
)

Ключевые кадры на основе сплайнов особенно полезны для 2D-перемещения объектов на экране.

В следующих видеороликах показаны различия между keyframes и keyframesWithSpline заданными одним и тем же набором координат x и y, по которым должна двигаться окружность.

keyframes keyframesWithSplines

Как видите, ключевые кадры на основе сплайнов обеспечивают более плавные переходы между точками, поскольку они используют кривые Безье для плавной анимации между элементами. Эта спецификация полезна для предустановленной анимации. Однако, если вы работаете с точками, заданными пользователем, предпочтительнее использовать пружины для достижения аналогичной плавности между точками, поскольку они прерываемы.

Повторить анимацию с помощью repeatable

repeatable запускает анимацию, зависящую от длительности (например, tween или keyframes ), многократно до достижения указанного количества итераций. Вы можете передать параметр repeatMode , чтобы указать, должна ли анимация повторяться, начиная с начала ( RepeatMode.Restart ) или с конца ( RepeatMode.Reverse ).

val value by animateFloatAsState(
    targetValue = 1f,
    animationSpec = repeatable(
        iterations = 3,
        animation = tween(durationMillis = 300),
        repeatMode = RepeatMode.Reverse
    ),
    label = "repeatable spec"
)

Повторяйте анимацию бесконечно с помощью infiniteRepeatable

infiniteRepeatable похож на repeatable , но повторяется бесконечное количество раз.

val value by animateFloatAsState(
    targetValue = 1f,
    animationSpec = infiniteRepeatable(
        animation = tween(durationMillis = 300),
        repeatMode = RepeatMode.Reverse
    ),
    label = "infinite repeatable"
)

В тестах с использованием ComposeTestRule анимации, использующие infiniteRepeatable , не запускаются. Компонент будет отображаться с использованием начального значения каждого анимированного параметра.

Мгновенно привязывайтесь к конечному значению с помощью snap

snap — это специальный AnimationSpec , который мгновенно переключает значение на конечное. Вы можете указать delayMillis , чтобы отложить начало анимации.

val value by animateFloatAsState(
    targetValue = 1f,
    animationSpec = snap(delayMillis = 50),
    label = "snap spec"
)

Настройте пользовательскую функцию сглаживания

Операции AnimationSpec основанные на длительности (например, tween или keyframes ), используют Easing для регулировки доли анимации. Это позволяет анимируемому значению ускоряться и замедляться, а не двигаться с постоянной скоростью. Доля — это значение от 0 (начало) до 1,0 (конец), указывающее на текущую точку анимации.

Функция Easing фактически принимает дробное значение от 0 до 1,0 и возвращает число с плавающей запятой. Возвращаемое значение может выходить за пределы диапазона, представляя собой перерегулирование или недорегулирование. Пользовательскую функцию Easing можно создать, как показано в приведенном ниже коде.

val CustomEasing = Easing { fraction -> fraction * fraction }

@Composable
fun EasingUsage() {
    val value by animateFloatAsState(
        targetValue = 1f,
        animationSpec = tween(
            durationMillis = 300,
            easing = CustomEasing
        ),
        label = "custom easing"
    )
    // ……
}

Compose предоставляет несколько встроенных функций Easing , охватывающих большинство сценариев использования. Дополнительную информацию о том, какие функции сглаживания использовать в зависимости от вашей ситуации, см. в разделе «Скорость — Material Design».

Анимируйте пользовательские типы данных, преобразуя их в AnimationVector и обратно.

Большинство API анимации Compose по умолчанию поддерживают типы данных Float , Color , Dp и другие базовые типы данных в качестве значений анимации, но иногда вам необходимо анимировать и другие типы данных, включая ваши собственные. Во время анимации любое анимируемое значение представляется в виде AnimationVector . Значение преобразуется в AnimationVector и наоборот с помощью соответствующего TwoWayConverter , чтобы основная система анимации могла обрабатывать их единообразно. Например, целое Int представляется в виде AnimationVector1D , содержащего одно значение типа float. TwoWayConverter для Int выглядит следующим образом:

val IntToVector: TwoWayConverter<Int, AnimationVector1D> =
    TwoWayConverter({ AnimationVector1D(it.toFloat()) }, { it.value.toInt() })

Color по сути, представляет собой набор из 4 значений: красный, зеленый, синий и альфа-канал, поэтому Color преобразуется в AnimationVector4D , содержащий 4 значения типа float. Таким образом, каждый тип данных, используемый в анимации, преобразуется либо в AnimationVector1D , AnimationVector2D , AnimationVector3D , либо AnimationVector4D в зависимости от его размерности. Это позволяет анимировать различные компоненты объекта независимо, каждый со своим собственным отслеживанием скорости. Доступ к встроенным преобразователям для основных типов данных можно получить с помощью таких преобразователей, как Color.VectorConverter или Dp.VectorConverter .

Если вы хотите добавить поддержку нового типа данных в качестве значения для анимации, вы можете создать собственный TwoWayConverter и передать его в API. Например, вы можете использовать animateValueAsState для анимации вашего пользовательского типа данных следующим образом:

data class MySize(val width: Dp, val height: Dp)

@Composable
fun MyAnimation(targetSize: MySize) {
    val animSize: MySize by animateValueAsState(
        targetSize,
        TwoWayConverter(
            convertToVector = { size: MySize ->
                // Extract a float value from each of the `Dp` fields.
                AnimationVector2D(size.width.value, size.height.value)
            },
            convertFromVector = { vector: AnimationVector2D ->
                MySize(vector.v1.dp, vector.v2.dp)
            }
        ),
        label = "size"
    )
}

В следующем списке представлены некоторые встроенные VectorConverter :

{% verbatim %} {% endverbatim %} {% verbatim %} {% endverbatim %}