Permalink
Browse files

RCTAnimation & RCTLayoutAnimation were decoupled from RCTUIManager

Reviewed By: javache

Differential Revision: D5351726

fbshipit-source-id: f13e5cd47483f2d5f9b194c10ae3fb6e99e08d84
  • Loading branch information...
shergin authored and facebook-github-bot committed Jul 3, 2017
1 parent e7c1cf5 commit 6312d67bcbf9b3af2f53b367d6a1f9f98bad52f8
@@ -0,0 +1,38 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <UIKit/UIKit.h>
#import <React/RCTAnimationType.h>
@interface RCTLayoutAnimation : NSObject
@property (nonatomic, readonly) NSTimeInterval duration;
@property (nonatomic, readonly) NSTimeInterval delay;
@property (nonatomic, readonly, copy) NSString *property;
@property (nonatomic, readonly) CGFloat springDamping;
@property (nonatomic, readonly) CGFloat initialVelocity;
@property (nonatomic, readonly) RCTAnimationType animationType;
+ (void)initializeStatics;
- (instancetype)initWithDuration:(NSTimeInterval)duration
delay:(NSTimeInterval)delay
property:(NSString *)property
springDamping:(CGFloat)springDamping
initialVelocity:(CGFloat)initialVelocity
animationType:(RCTAnimationType)animationType;
- (instancetype)initWithDuration:(NSTimeInterval)duration
config:(NSDictionary *)config;
- (void)performAnimations:(void (^)(void))animations
withCompletionBlock:(void (^)(BOOL completed))completionBlock;
@end
@@ -0,0 +1,155 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import "RCTLayoutAnimation.h"
#import "RCTConvert.h"
@implementation RCTLayoutAnimation
static UIViewAnimationCurve _currentKeyboardAnimationCurve;
static UIViewAnimationOptions UIViewAnimationOptionsFromRCTAnimationType(RCTAnimationType type)
{
switch (type) {
case RCTAnimationTypeLinear:
return UIViewAnimationOptionCurveLinear;
case RCTAnimationTypeEaseIn:
return UIViewAnimationOptionCurveEaseIn;
case RCTAnimationTypeEaseOut:
return UIViewAnimationOptionCurveEaseOut;
case RCTAnimationTypeEaseInEaseOut:
return UIViewAnimationOptionCurveEaseInOut;
case RCTAnimationTypeKeyboard:
// http://stackoverflow.com/questions/18870447/how-to-use-the-default-ios7-uianimation-curve
return (UIViewAnimationOptions)(_currentKeyboardAnimationCurve << 16);
default:
RCTLogError(@"Unsupported animation type %zd", type);
return UIViewAnimationOptionCurveEaseInOut;
}
}
// Use a custom initialization function rather than implementing `+initialize` so that we can control
// when the initialization code runs. `+initialize` runs immediately before the first message is sent
// to the class which may be too late for us. By this time, we may have missed some
// `UIKeyboardWillChangeFrameNotification`s.
+ (void)initializeStatics
{
#if !TARGET_OS_TV
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillChangeFrame:)
name:UIKeyboardWillChangeFrameNotification
object:nil];
});
#endif
}
+ (void)keyboardWillChangeFrame:(NSNotification *)notification
{
#if !TARGET_OS_TV
NSDictionary *userInfo = notification.userInfo;
_currentKeyboardAnimationCurve = [userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue];
#endif
}
- (instancetype)initWithDuration:(NSTimeInterval)duration
delay:(NSTimeInterval)delay
property:(NSString *)property
springDamping:(CGFloat)springDamping
initialVelocity:(CGFloat)initialVelocity
animationType:(RCTAnimationType)animationType
{
if (self = [super init]) {
_duration = duration;
_delay = delay;
_property = property;
_springDamping = springDamping;
_initialVelocity = initialVelocity;
_animationType = animationType;
}
return self;
}
- (instancetype)initWithDuration:(NSTimeInterval)duration
config:(NSDictionary *)config
{
if (!config) {
return nil;
}
if (self = [super init]) {
_property = [RCTConvert NSString:config[@"property"]];
_duration = [RCTConvert NSTimeInterval:config[@"duration"]] ?: duration;
if (_duration > 0.0 && _duration < 0.01) {
RCTLogError(@"RCTLayoutAnimationGroup expects timings to be in ms, not seconds.");
_duration = _duration * 1000.0;
}
_delay = [RCTConvert NSTimeInterval:config[@"delay"]];
if (_delay > 0.0 && _delay < 0.01) {
RCTLogError(@"RCTLayoutAnimationGroup expects timings to be in ms, not seconds.");
_delay = _delay * 1000.0;
}
_animationType = [RCTConvert RCTAnimationType:config[@"type"]];
if (_animationType == RCTAnimationTypeSpring) {
_springDamping = [RCTConvert CGFloat:config[@"springDamping"]];
_initialVelocity = [RCTConvert CGFloat:config[@"initialVelocity"]];
}
}
return self;
}
- (void)performAnimations:(void (^)(void))animations
withCompletionBlock:(void (^)(BOOL completed))completionBlock
{
if (_animationType == RCTAnimationTypeSpring) {
[UIView animateWithDuration:_duration
delay:_delay
usingSpringWithDamping:_springDamping
initialSpringVelocity:_initialVelocity
options:UIViewAnimationOptionBeginFromCurrentState
animations:animations
completion:completionBlock];
} else {
UIViewAnimationOptions options =
UIViewAnimationOptionBeginFromCurrentState |
UIViewAnimationOptionsFromRCTAnimationType(_animationType);
[UIView animateWithDuration:_duration
delay:_delay
options:options
animations:animations
completion:completionBlock];
}
}
- (BOOL)isEqual:(RCTLayoutAnimation *)animation
{
return
_duration == animation.duration &&
_delay == animation.delay &&
(_property == animation.property || [_property isEqualToString:animation.property]) &&
_springDamping == animation.springDamping &&
_initialVelocity == animation.initialVelocity &&
_animationType == animation.animationType;
}
- (NSString *)description
{
return [NSString stringWithFormat:@"<%@: %p; duration: %f; delay: %f; property: %@; springDamping: %f; initialVelocity: %f; animationType: %li;>",
NSStringFromClass([self class]), self, _duration, _delay, _property, _springDamping, _initialVelocity, (long)_animationType];
}
@end
@@ -0,0 +1,32 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <UIKit/UIKit.h>
#import <React/RCTBridgeModule.h>
@class RCTLayoutAnimation;
@interface RCTLayoutAnimationGroup : NSObject
@property (nonatomic, readonly) RCTLayoutAnimation *creatingLayoutAnimation;
@property (nonatomic, readonly) RCTLayoutAnimation *updatingLayoutAnimation;
@property (nonatomic, readonly) RCTLayoutAnimation *deletingLayoutAnimation;
@property (nonatomic, copy) RCTResponseSenderBlock callback;
- (instancetype)initWithCreatingLayoutAnimation:(RCTLayoutAnimation *)creatingLayoutAnimation
updatingLayoutAnimation:(RCTLayoutAnimation *)updatingLayoutAnimation
deletingLayoutAnimation:(RCTLayoutAnimation *)deletingLayoutAnimation
callback:(RCTResponseSenderBlock)callback;
- (instancetype)initWithConfig:(NSDictionary *)config
callback:(RCTResponseSenderBlock)callback;
@end
@@ -0,0 +1,74 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import "RCTLayoutAnimationGroup.h"
#import "RCTLayoutAnimation.h"
#import "RCTConvert.h"
@implementation RCTLayoutAnimationGroup
- (instancetype)initWithCreatingLayoutAnimation:(RCTLayoutAnimation *)creatingLayoutAnimation
updatingLayoutAnimation:(RCTLayoutAnimation *)updatingLayoutAnimation
deletingLayoutAnimation:(RCTLayoutAnimation *)deletingLayoutAnimation
callback:(RCTResponseSenderBlock)callback
{
if (self = [super init]) {
_creatingLayoutAnimation = creatingLayoutAnimation;
_updatingLayoutAnimation = updatingLayoutAnimation;
_deletingLayoutAnimation = deletingLayoutAnimation;
_callback = callback;
}
return self;
}
- (instancetype)initWithConfig:(NSDictionary *)config
callback:(RCTResponseSenderBlock)callback
{
if (!config) {
return nil;
}
if (self = [super init]) {
NSTimeInterval duration = [RCTConvert NSTimeInterval:config[@"duration"]];
if (duration > 0.0 && duration < 0.01) {
RCTLogError(@"RCTLayoutAnimationGroup expects timings to be in ms, not seconds.");
duration = duration * 1000.0;
}
_creatingLayoutAnimation = [[RCTLayoutAnimation alloc] initWithDuration:duration config:config[@"create"]];
_updatingLayoutAnimation = [[RCTLayoutAnimation alloc] initWithDuration:duration config:config[@"update"]];
_deletingLayoutAnimation = [[RCTLayoutAnimation alloc] initWithDuration:duration config:config[@"delete"]];
_callback = callback;
}
return self;
}
- (BOOL)isEqual:(RCTLayoutAnimationGroup *)layoutAnimation
{
RCTLayoutAnimation *creatingLayoutAnimation = layoutAnimation.creatingLayoutAnimation;
RCTLayoutAnimation *updatingLayoutAnimation = layoutAnimation.updatingLayoutAnimation;
RCTLayoutAnimation *deletingLayoutAnimation = layoutAnimation.deletingLayoutAnimation;
return
(_creatingLayoutAnimation == creatingLayoutAnimation || [_creatingLayoutAnimation isEqual:creatingLayoutAnimation]) &&
(_updatingLayoutAnimation == updatingLayoutAnimation || [_updatingLayoutAnimation isEqual:updatingLayoutAnimation]) &&
(_deletingLayoutAnimation == deletingLayoutAnimation || [_deletingLayoutAnimation isEqual:deletingLayoutAnimation]);
}
- (NSString *)description
{
return [NSString stringWithFormat:@"<%@: %p; creatingLayoutAnimation: %@; updatingLayoutAnimation: %@; deletingLayoutAnimation: %@>",
NSStringFromClass([self class]), self, [_creatingLayoutAnimation description], [_updatingLayoutAnimation description], [_deletingLayoutAnimation description]];
}
@end
@@ -59,6 +59,7 @@ RCT_EXTERN NSString *const RCTUIManagerDidRemoveRootViewNotification;
*/
RCT_EXTERN NSString *const RCTUIManagerRootViewKey;
@class RCTLayoutAnimationGroup;
@class RCTUIManagerObserverCoordinator;
/**
@@ -115,6 +116,13 @@ RCT_EXTERN NSString *const RCTUIManagerRootViewKey;
*/
- (void)setBackgroundColor:(UIColor *)color forView:(UIView *)view;
/**
* Sets up layout animation which will perform on next layout pass.
* The animation will affect only one next layout pass.
* Must be called on the main queue.
*/
- (void)setNextLayoutAnimationGroup:(RCTLayoutAnimationGroup *)layoutAnimationGroup;
/**
* Schedule a block to be executed on the UI thread. Useful if you need to execute
* view logic after all currently queued view updates have completed.
Oops, something went wrong.

0 comments on commit 6312d67

Please sign in to comment.