blob: 8cb0e448da736dcbdc42a9d170e716c75e1d0d6c [file] [edit]
/*
Copyright 2017-present The Material Motion Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#import <Foundation/Foundation.h>
#import <QuartzCore/QuartzCore.h>
#ifdef IS_BAZEL_BUILD
#import "MotionInterchange.h"
#else
#import <MotionInterchange/MotionInterchange.h>
#endif
#import "MDMAnimatableKeyPaths.h"
#import "MDMCoreAnimationTraceable.h"
/**
An animator adds Core Animation animations to a layer using animation traits.
*/
NS_SWIFT_NAME(MotionAnimator)
@interface MDMMotionAnimator : NSObject <MDMCoreAnimationTraceable>
#pragma mark - Configuring animation behavior
/**
The scaling factor to apply to all time-related values.
For example, a timeScaleFactor of 2 will double the length of all animations.
1.0 by default.
*/
@property(nonatomic, assign) CGFloat timeScaleFactor;
/**
If enabled, all animations will start from their current presentation value.
If disabled, animations will start from the first value in the values array.
Disabled by default.
*/
@property(nonatomic, assign) BOOL beginFromCurrentState;
/**
If enabled, animations will calculate their values in relation to their destination value.
Additive animations can be stacked. This is most commonly used to change the destination of an
animation mid-way through in such a way that momentum appears to be conserved.
Enabled by default.
*/
@property(nonatomic, assign) BOOL additive;
#pragma mark - Explicitly animating between values
/**
Adds a single animation to the layer with the given traits structure.
If `additive` is disabled, the animation will be added to the layer with the keyPath as its key.
In this case, multiple invocations of this function on the same key path will remove the
animations added from prior invocations.
@param traits The traits to be used for the animation.
@param layer The layer to be animated.
@param values The values to be used in the animation. Must contain exactly two values. Supported
UIKit types will be coerced to their Core Animation equivalent. Supported UIKit
values include UIColor and UIBezierPath.
@param keyPath The key path of the property to be animated.
*/
- (void)animateWithTraits:(nonnull MDMAnimationTraits *)traits
between:(nonnull NSArray *)values
layer:(nonnull CALayer *)layer
keyPath:(nonnull MDMAnimatableKeyPath)keyPath;
/**
Adds a single animation to the layer with the given traits structure.
If `additive` is disabled, the animation will be added to the layer with the keyPath as its key.
In this case, multiple invocations of this function on the same key path will remove the
animations added from prior invocations.
@param traits The traits to be used for the animation.
@param layer The layer to be animated.
@param values The values to be used in the animation. Must contain exactly two values.
Supported UIKit types will be coerced to their Core Animation equivalent.
@param keyPath The key path of the property to be animated.
@param completion A block object to be executed when the animation ends or is removed from the
animation hierarchy. If the duration of the animation is 0, this block is
executed immediately. The block is escaping and will be released once the
animations have completed. The provided `finished` argument is currently always
YES.
*/
- (void)animateWithTraits:(nonnull MDMAnimationTraits *)traits
between:(nonnull NSArray *)values
layer:(nonnull CALayer *)layer
keyPath:(nonnull MDMAnimatableKeyPath)keyPath
completion:(nullable void(^)(BOOL finished))completion;
/**
If enabled, explicitly-provided values will be reversed before animating.
This property only affects the animateWithTraits:between:... family of methods.
Disabled by default.
*/
@property(nonatomic, assign) BOOL shouldReverseValues;
#pragma mark - Implicitly animating
/**
Performs `animations` using the traits provided.
@param traits The traits to be used for the animation.
@param animations The block to be executed. Any animatable properties changed within this block
will result in animations being added to the view's layer with the provided
traits. The block is non-escaping.
*/
- (void)animateWithTraits:(nonnull MDMAnimationTraits *)traits
animations:(nonnull void(^)(void))animations;
/**
Performs `animations` using the traits provided and executes the completion handler once all added
animations have completed.
@param traits The traits to be used for the animation.
@param animations The block to be executed. Any animatable properties changed within this block
will result in animations being added to the view's layer with the provided
traits. The block is non-escaping.
@param completion A block object to be executed once the animation sequence ends or it has been
removed from the animation hierarchy. If the duration of the animation is 0,
this block is executed immediately. The block is escaping and will be released
once the animation sequence has completed. The provided `finished` argument is
currently always YES.
*/
- (void)animateWithTraits:(nonnull MDMAnimationTraits *)traits
animations:(nonnull void (^)(void))animations
completion:(nullable void(^)(BOOL finished))completion;
#pragma mark - Managing active animations
/**
Removes every animation added by this animator.
Removing animations in this manner will give the appearance of each animated layer property
instantaneously jumping to its animated destination.
*/
- (void)removeAllAnimations;
/**
Commits the presentation layer value to the model layer value for every active animation's key path
and then removes every animation.
This method is most commonly called in reaction to the initiation of a gesture so that any
in-flight animations are stopped at their current on-screen position.
*/
- (void)stopAllAnimations;
@end
@interface MDMMotionAnimator (UIKitEquivalency)
/**
Similar to the UIKit method of the same name with some intentional differences in behavior.
This API does not disable user interaction during animations, unlike the default behavior of
UIView's similar API.
Like the UIKit API, this method performs the specified animations immediately using the
UIViewAnimationOptionCurveEaseInOut animation option.
@param duration From UIKit's documentation: "The total duration of the animations, measured in
seconds. If you specify a negative value or 0, the changes are made without
animating them."
@param animations From UIKit's documentation: "A block object containing the changes to commit to
the views. This is where you programmatically change any animatable properties of
the views in your view hierarchy. This block takes no parameters and has no
return value. This parameter must not be NULL."
Supports animating additional CALayer properties beyond what UIView's similar API
supports. See MDMAnimatableKeyPaths for a full list of implicilty animatable
CALayer properties.
*/
+ (void)animateWithDuration:(NSTimeInterval)duration
animations:(void (^ __nonnull)(void))animations;
/**
Similar to the UIKit method of the same name with some intentional differences in behavior.
This API does not disable user interaction during animations, unlike the default behavior of
UIView's similar API.
Like the UIKit API, this method performs the specified animations immediately using the
UIViewAnimationOptionCurveEaseInOut animation option.
@param duration From UIKit's documentation: "The total duration of the animations, measured in
seconds. If you specify a negative value or 0, the changes are made without
animating them."
@param animations From UIKit's documentation: "A block object containing the changes to commit to
the views. This is where you programmatically change any animatable properties of
the views in your view hierarchy. This block takes no parameters and has no
return value. This parameter must not be NULL."
Supports animating additional CALayer properties beyond what UIView's similar API
supports. See MDMAnimatableKeyPaths for a full list of implicilty animatable
CALayer properties.
@param completion From UIKit's documentation: "A block object to be executed when the animation
sequence ends. This block has no return value and takes a single Boolean argument
that indicates whether or not the animations actually finished before the
completion handler was called."
Unlike UIKit's API, if the duration of the animation is 0, this block is
performed immediately. This parameter may be NULL.
*/
+ (void)animateWithDuration:(NSTimeInterval)duration
animations:(void (^ __nonnull)(void))animations
completion:(void (^ __nullable)(BOOL finished))completion;
/**
Similar to the UIKit method of the same name with some intentional differences in behavior.
This API does not disable user interaction during animations, unlike the default behavior of
UIView's similar API.
Like the UIKit API, this method performs the specified animations immediately.
The only options that are presently supported are the UIViewAnimationOptionCurve flags.
@param duration From UIKit's documentation: "The total duration of the animations, measured in
seconds. If you specify a negative value or 0, the changes are made without
animating them."
@param delay From UIKit's documentation: "The amount of time (measured in seconds) to wait
before beginning the animations. Specify a value of 0 to begin the animations
immediately."
@param options From UIKit's documentation: "A mask of options indicating how you want to perform
the animations. For a list of valid constants, see UIViewAnimationOptions." Only
the UIViewAnimationOptionCurve flags are supported presently.
@param animations From UIKit's documentation: "A block object containing the changes to commit to
the views. This is where you programmatically change any animatable properties of
the views in your view hierarchy. This block takes no parameters and has no
return value. This parameter must not be NULL."
Supports animating additional CALayer properties beyond what UIView's similar API
supports. See MDMAnimatableKeyPaths for a full list of implicilty animatable
CALayer properties.
@param completion From UIKit's documentation: "A block object to be executed when the animation
sequence ends. This block has no return value and takes a single Boolean argument
that indicates whether or not the animations actually finished before the
completion handler was called."
Unlike UIKit's API, if the duration of the animation is 0, this block is
performed immediately. This parameter may be NULL.
*/
+ (void)animateWithDuration:(NSTimeInterval)duration
delay:(NSTimeInterval)delay
options:(UIViewAnimationOptions)options
animations:(void (^ __nonnull)(void))animations
completion:(void (^ __nullable)(BOOL finished))completion;
/**
Similar to the UIKit method of the same name with some intentional differences in behavior.
This API does not disable user interaction during animations, unlike the default behavior of
UIView's similar API.
Like the UIKit API, this method performs the specified animations immediately.
@param duration From UIKit's documentation: "The total duration of the animations, measured in
seconds. If you specify a negative value or 0, the changes are made without
animating them."
@param delay From UIKit's documentation: "The amount of time (measured in seconds) to wait
before beginning the animations. Specify a value of 0 to begin the animations
immediately."
@param options Ignored.
@param dampingRatio From UIKit's documentation: "The damping ratio for the spring animation as it
approaches its quiescent state. To smoothly decelerate the animation without
oscillation, use a value of 1. Employ a damping ratio closer to zero to
increase oscillation."
@param velocity From UIKit's documentation: "The initial spring velocity. For smooth start to
the animation, match this value to the view’s velocity as it was prior to
attachment."
Unlike UIKit's API, the initial velocity value is measured in terms of absolute
units of motion. For example, if animating a position from 0 to 10 with an
initial velocity of 100 points/second, the provided initial velocity value
should be 100.
@param animations From UIKit's documentation: "A block object containing the changes to commit to
the views. This is where you programmatically change any animatable properties
of the views in your view hierarchy. This block takes no parameters and has no
return value. This parameter must not be NULL."
Supports animating additional CALayer properties beyond what UIView's similar
API supports. See MDMAnimatableKeyPaths for a full list of implicilty
animatable CALayer properties.
@param completion From UIKit's documentation: "A block object to be executed when the animation
sequence ends. This block has no return value and takes a single Boolean
argument that indicates whether or not the animations actually finished before
the completion handler was called."
Unlike UIKit's API, if the duration of the animation is 0, this block is
performed immediately. This parameter may be NULL.
*/
+ (void)animateWithDuration:(NSTimeInterval)duration
delay:(NSTimeInterval)delay
usingSpringWithDamping:(CGFloat)dampingRatio
initialSpringVelocity:(CGFloat)velocity
options:(UIViewAnimationOptions)options
animations:(void (^ __nonnull)(void))animations
completion:(void (^ __nullable)(BOOL finished))completion;
@end
@interface MDMMotionAnimator (Legacy)
/**
To be deprecated. Use animateWithTraits:between:layer:keyPath instead.
*/
- (void)animateWithTiming:(MDMMotionTiming)timing
toLayer:(nonnull CALayer *)layer
withValues:(nonnull NSArray *)values
keyPath:(nonnull MDMAnimatableKeyPath)keyPath;
/**
To be deprecated. Use animateWithTraits:between:layer:keyPath:completion: instead.
*/
- (void)animateWithTiming:(MDMMotionTiming)timing
toLayer:(nonnull CALayer *)layer
withValues:(nonnull NSArray *)values
keyPath:(nonnull MDMAnimatableKeyPath)keyPath
completion:(nullable void(^)(void))completion;
/**
To be deprecated. Use animateWithTraits:animations: instead.
*/
- (void)animateWithTiming:(MDMMotionTiming)timing
animations:(nonnull void(^)(void))animations;
/**
To be deprecated. Use animateWithTraits:animations:completion: instead.
*/
- (void)animateWithTiming:(MDMMotionTiming)timing
animations:(nonnull void (^)(void))animations
completion:(nullable void(^)(void))completion;
@end
@interface MDMMotionAnimator (ImplicitLayerAnimations)
/**
Returns a layer delegate that solely implements actionForLayer:forKey:.
Assign this delegate to a standalone CALayer (one created using [[CALayer alloc] init]) in order to
be able to implicitly animate its properties with MDMMotionAnimator. This is not necessary for
layers that are backing a UIView.
*/
+ (nonnull id<CALayerDelegate>)sharedLayerDelegate
__deprecated_msg("No longer needed for implicit animations of headless layers.");
@end