Многие 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
.
stiffness
определяет, как быстро пружина должна двигаться к конечному значению. Значение по умолчанию — Spring.StiffnessMedium
.
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
.
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
, которые охватывают большинство случаев использования. См. Speed - Material Design для получения дополнительной информации о том, какой Easing использовать в зависимости от вашего сценария.
-
FastOutSlowInEasing
-
LinearOutSlowInEasing
-
FastOutLinearEasing
-
LinearEasing
-
CubicBezierEasing
- Смотреть больше
Анимируйте пользовательские типы данных путем преобразования в AnimationVector
и обратно
Большинство API анимации Compose поддерживают Float
, Color
, Dp
и другие базовые типы данных в качестве значений анимации по умолчанию, но иногда вам нужно анимировать другие типы данных, включая ваши собственные. Во время анимации любое анимационное значение представляется как AnimationVector
. Значение преобразуется в AnimationVector
и наоборот соответствующим TwoWayConverter
, чтобы основная система анимации могла обрабатывать их единообразно. Например, Int
представляется как AnimationVector1D
, который содержит одно значение с плавающей точкой. TwoWayConverter
для Int
выглядит следующим образом:
val IntToVector: TwoWayConverter<Int, AnimationVector1D> = TwoWayConverter({ AnimationVector1D(it.toFloat()) }, { it.value.toInt() })
Color
по сути является набором из 4 значений: красного, зеленого, синего и альфа, поэтому Color
преобразуется в AnimationVector4D
, который содержит 4 значения с плавающей точкой. Таким образом, каждый тип данных, используемый в анимации, преобразуется в 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
:
-
Color.VectorConverter
-
Dp.VectorConverter
-
Offset.VectorConverter
-
Int.VectorConverter
-
Float.VectorConverter
-
IntSize.VectorConverter
Рекомендовано для вас
- Примечание: текст ссылки отображается, когда JavaScript отключен.
- Ценностно-ориентированная анимация
- Итеративная разработка кода {:#iterative-code-dev }
- Анимации в Compose