One Logo Pool Ball
SwiftUICore · IOS API REFERENCE

CustomAnimation

protocol · iOS 17.0+ · SDK 27.1

@preconcurrency protocol CustomAnimation : Hashable, Sendable

A type that defines how an animatable value changes over time. Use this protocol to create a type that changes an animatable value over time, which produces a custom visual transition of a view. For example, the follow code changes an animatable value using an elastic ease-in ease-out function: struct ElasticEaseInEaseOutAnimation: CustomAnimation { let duration: TimeInterval func animate<V>(value: V, time: TimeInterval, context: inout AnimationContext<V>) -> V? where V : VectorArithmetic { if time > duration { return nil } // The animation has finished. let p = time / duration let s = sin((20 * p - 11.125) * ((2 * Double.pi) / 4.5)) if p < 0.5 { return value.scaled(by: -(pow(2, 20 * p - 10) * s) / 2) } else { return value.scaled(by: (pow(2, -20 * p + 10) * s) / 2 + 1) } } } > Note: To maintain state during the life span of a custom animation, use the ``AnimationContext/state`` property available on the `context` parameter value. You can also use context's ``AnimationContext/environment`` property to retrieve environment values from the view that created the custom animation. For more information, see ``AnimationContext``. To create an ``Animation`` instance of a custom animation, use the ``Animation/init(_:)`` initializer, passing in an instance of a custom animation; for example: Animation(ElasticEaseInEaseOutAnimation(duration: 5.0)) To help make view code more readable, extend ``Animation`` and add a static property and function that returns an `Animation` instance of a custom animation. For example, the following code adds the static property `elasticEaseInEaseOut` that returns the elastic ease-in ease-out animation with a default duration of `0.35` seconds. Next, the code adds a method that returns the animation with a specified duration. extension Animation { static var elasticEaseInEaseOut: Animation { elasticEaseInEaseOut(duration: 0.35) } static func elasticEaseInEaseOut(duration: TimeInterval) -> Animation { Animation(ElasticEaseInEaseOutAnimation(duration: duration)) } } To animate a view with the elastic ease-in ease-out animation, a view calls either `.elasticEaseInEaseOut` or `.elasticEaseInEaseOut(duration:)`. For example, the follow code includes an Animate button that, when clicked, animates a circle as it moves from one edge of the view to the other, using the elastic ease-in ease-out animation with a duration of `5` seconds: struct ElasticEaseInEaseOutView: View { @State private var isActive = false var body: some View { VStack(alignment: isActive ? .trailing : .leading) { Circle() .frame(width: 100.0) .foregroundColor(.accentColor) Button("Animate") { withAnimation(.elasticEaseInEaseOut(duration: 5.0)) { isActive.toggle() } } .frame(maxWidth: .infinity) } .padding() } } @Video(source: "animation-20-elastic.mp4", poster: "animation-20-elastic.png", alt: "A video that shows a circle that moves from one edge of the view to the other using an elastic ease-in ease-out animation. The circle's initial position is near the leading edge of the view. The circle begins moving slightly towards the leading, then towards trail edges of the view before it moves off the leading edge showing only two-thirds of the circle. The circle then moves quickly to the trailing edge of the view, going slightly beyond the edge so that only two-thirds of the circle is visible. The circle bounces back into full view before settling into position near the trailing edge of the view. The circle repeats this animation in reverse, going from the trailing edge of the view to the leading edge.")

Members (2)

method · iOS 17.0+

shouldMerge

Swift declaration
func shouldMerge<V>(previous: Animation, value: V, time: TimeInterval, context: inout AnimationContext<V>) -> Bool where V : VectorArithmetic

Determines whether an instance of the animation can merge with other running animations. When a view creates a new animation on an animatable value that already is running an animation, the system calls the `shouldMerge(previous:value:time:context:)` method on the new instance to determine whether it can merge the two instances. Implement this method if the animation can merge with other instances. The default implementation returns `false`. If `shouldMerge(previous:value:time:context:)` returns `true`, the system merges the new animation instance with the previous animation. The system provides to the new instance the state and elapsed time from the previous one. Then it removes the previous animation. If this method returns `false`, the system doesn't merge the animation with the previous one. Instead, both animations run together and the system combines their results. If your custom animation needs to maintain state between calls to the `shouldMerge(previous:value:time:context:)` method, store the state data in `context`. This makes the data available to the method next time the system calls it. To learn more, see ``AnimationContext``. - Parameters: - previous: The previous running animation. - value: The vector to animate towards. - time: The amount of time since the start of the previous animation. - context: An instance of ``AnimationContext`` that provides access to state and the animation environment. - Returns: A Boolean value of `true` if the animation should merge with the previous animation; otherwise, `false`.

Omit the output parameters from the call. The result contains $ret and $out, with context inside $out.

method · iOS 17.0+

velocity

Swift declaration
func velocity<V>(value: V, time: TimeInterval, context: AnimationContext<V>) -> V? where V : VectorArithmetic

Calculates the velocity of the animation at a specified time. Implement this method to provide the velocity of the animation at a given time. Should subsequent animations merge with the animation, the system preserves continuity of the velocity between animations. The default implementation of this method returns `nil`. > Note: State and environment data is available to this method via the `context` parameter, but `context` is read-only. This behavior is different than with ``animate(value:time:context:)`` and ``shouldMerge(previous:value:time:context:)`` where `context` is an `inout` parameter, letting you change the context including state data of the animation. For more information about managing state data in a custom animation, see ``AnimationContext``. - Parameters: - value: The vector to animate towards. - time: The amount of time since the start of the animation. - context: An instance of ``AnimationContext`` that provides access to state and the animation environment. - Returns: The current velocity of the animation, or `nil` if the animation has finished.

Skipped declarations

No declarations were skipped in this snapshot.

All SwiftUICore types →