Skip to content

Commit

Permalink
Fix and refactor animations options (#4880)
Browse files Browse the repository at this point in the history
  • Loading branch information
yogevbd authored Mar 19, 2019
1 parent f484c2c commit a98f187
Show file tree
Hide file tree
Showing 24 changed files with 292 additions and 133 deletions.
12 changes: 12 additions & 0 deletions lib/ios/RNNAnimationConfigurationOptions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#import "RNNOptions.h"

@interface RNNAnimationConfigurationOptions : RNNOptions

@property (nonatomic, strong) Double* from;
@property (nonatomic, strong) Double* to;
@property (nonatomic, strong) Double* duration;
@property (nonatomic, strong) Double* startDelay;

- (BOOL)hasAnimation;

@end
20 changes: 20 additions & 0 deletions lib/ios/RNNAnimationConfigurationOptions.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#import "RNNAnimationConfigurationOptions.h"

@implementation RNNAnimationConfigurationOptions

- (instancetype)initWithDict:(NSDictionary *)dict {
self = [super init];

self.from = [DoubleParser parse:dict key:@"from"];
self.to = [DoubleParser parse:dict key:@"to"];
self.startDelay = [DoubleParser parse:dict key:@"startDelay"];
self.duration = [DoubleParser parse:dict key:@"duration"];

return self;
}

- (BOOL)hasAnimation {
return self.from.hasValue && self.to.hasValue;
}

@end
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
#import "RNNOptions.h"
#import "RNNTransitionStateHolder.h"
#import "RNNScreenTransition.h"

@interface RNNTransitionsOptions : RNNOptions
@interface RNNAnimationsOptions : RNNOptions

@property (nonatomic, strong) RNNScreenTransition* push;
@property (nonatomic, strong) RNNScreenTransition* pop;
Expand Down
18 changes: 18 additions & 0 deletions lib/ios/RNNAnimationsOptions.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#import "RNNAnimationsOptions.h"

@implementation RNNAnimationsOptions

- (instancetype)initWithDict:(NSDictionary *)dict {
self = [super init];

self.push = [[RNNScreenTransition alloc] initWithDict:dict[@"push"]];
self.pop = [[RNNScreenTransition alloc] initWithDict:dict[@"pop"]];
self.showModal = [[RNNScreenTransition alloc] initWithDict:dict[@"showModal"]];
self.dismissModal = [[RNNScreenTransition alloc] initWithDict:dict[@"dismissModal"]];
self.setStackRoot = [[RNNScreenTransition alloc] initWithDict:dict[@"setStackRoot"]];
self.setRoot = [[RNNScreenTransition alloc] initWithDict:dict[@"setRoot"]];

return self;
}

@end
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#import <Foundation/Foundation.h>
#import "RNNScreenTransition.h"

@interface RNNModalAnimation : NSObject <UIViewControllerAnimatedTransitioning>
@interface RNNAnimationsTransitionDelegate : NSObject <UIViewControllerAnimatedTransitioning, UIViewControllerTransitioningDelegate>

@property (nonatomic, strong) RNNScreenTransition* screenTransition;
@property (nonatomic) BOOL isDismiss;
Expand Down
60 changes: 60 additions & 0 deletions lib/ios/RNNAnimationsTransitionDelegate.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#import "RNNAnimationsTransitionDelegate.h"

@implementation RNNAnimationsTransitionDelegate

- (instancetype)initWithScreenTransition:(RNNScreenTransition *)screenTransition isDismiss:(BOOL)isDismiss {
self = [super init];
self.screenTransition = screenTransition;
self.isDismiss = isDismiss;
return self;
}

- (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source {
return self;
}

- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed {
return self;
}

- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext {
return self.screenTransition.maxDuration / 1000;
}

- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {
UIViewController* toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIViewController* fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];

[CATransaction begin];
[CATransaction setCompletionBlock:^{
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
}];

if (_isDismiss) {
[[transitionContext containerView] addSubview:toViewController.view];
[[transitionContext containerView] addSubview:fromViewController.view];
[self animateElement:self.screenTransition.content view:fromViewController.view elementName:@"content"];
} else {
[[transitionContext containerView] addSubview:toViewController.view];
[self animateElement:self.screenTransition.content view:toViewController.view elementName:@"content"];
}

[CATransaction commit];
}

- (void)animationWithKeyPath:(NSString *)keyPath from:(id)from to:(id)to duration:(CFTimeInterval)duration forView:(UIView *)view animationName:(NSString *)animationName {
CABasicAnimation *animation = [CABasicAnimation animation];
animation.keyPath = keyPath;
animation.fromValue = from;
animation.toValue = to;
animation.duration = duration / 1000;
[view.layer addAnimation:animation forKey:animationName];
}

- (void)animateElement:(RNNElementTransitionOptions *)element view:(UIView *)view elementName:(NSString *)elementName {
[self animationWithKeyPath:@"position.x" from:@(view.layer.position.x + [element.x.from getWithDefaultValue:0]) to:@(view.layer.position.x + [element.x.to getWithDefaultValue:0]) duration:[element.x.duration getWithDefaultValue:1] forView:view animationName:@"element.position.x"];
[self animationWithKeyPath:@"position.y" from:@(view.layer.position.y + [element.y.from getWithDefaultValue:0]) to:@(view.layer.position.y + [element.y.to getWithDefaultValue:0]) duration:[element.y.duration getWithDefaultValue:1] forView:view animationName:[NSString stringWithFormat:@"%@.position.y", elementName]];
[self animationWithKeyPath:@"opacity" from:@([element.alpha.from getWithDefaultValue:1]) to:@([element.alpha.to getWithDefaultValue:1]) duration:[element.alpha.duration getWithDefaultValue:1] forView:view animationName:[NSString stringWithFormat:@"%@.alpha", elementName]];
}

@end
4 changes: 2 additions & 2 deletions lib/ios/RNNAnimator.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "RNNAnimationOptions.h"
#import "RNNSharedElementAnimationOptions.h"

@interface RNNAnimator : NSObject <UIViewControllerAnimatedTransitioning>

-(instancetype)initWithTransitionOptions:(RNNAnimationOptions *)transitionOptions;
-(instancetype)initWithTransitionOptions:(RNNSharedElementAnimationOptions *)transitionOptions;

@end
6 changes: 3 additions & 3 deletions lib/ios/RNNAnimator.m
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
#import "RNNTransition.h"

@interface RNNAnimator()
@property (nonatomic, strong) RNNAnimationOptions* transitionOptions;
@property (nonatomic, strong) RNNSharedElementAnimationOptions* transitionOptions;
@property (nonatomic) BOOL backButton;
@property (nonatomic, weak) UIViewController* fromVC;
@property (nonatomic, weak) UIViewController* toVC;
@end

@implementation RNNAnimator

-(instancetype)initWithTransitionOptions:(RNNAnimationOptions *)transitionOptions {
-(instancetype)initWithTransitionOptions:(RNNSharedElementAnimationOptions *)transitionOptions {
self = [super init];
if (transitionOptions.animations) {
[self setupTransition:transitionOptions];
Expand All @@ -21,7 +21,7 @@ -(instancetype)initWithTransitionOptions:(RNNAnimationOptions *)transitionOption
return self;
}

-(void)setupTransition:(RNNAnimationOptions *)transitionOptions {
-(void)setupTransition:(RNNSharedElementAnimationOptions *)transitionOptions {
self.transitionOptions = transitionOptions;
if (!transitionOptions.animations) {
[[NSException exceptionWithName:NSInvalidArgumentException reason:@"No animations" userInfo:nil] raise];
Expand Down
18 changes: 18 additions & 0 deletions lib/ios/RNNElementTransitionOptions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#import "RNNOptions.h"
#import "RNNAnimationConfigurationOptions.h"

@interface RNNElementTransitionOptions : RNNOptions

@property (nonatomic, strong) RNNAnimationConfigurationOptions* alpha;
@property (nonatomic, strong) RNNAnimationConfigurationOptions* x;
@property (nonatomic, strong) RNNAnimationConfigurationOptions* y;
@property (nonatomic, strong) RNNAnimationConfigurationOptions* scaleX;
@property (nonatomic, strong) RNNAnimationConfigurationOptions* scaleY;
@property (nonatomic, strong) RNNAnimationConfigurationOptions* rotationX;
@property (nonatomic, strong) RNNAnimationConfigurationOptions* rotationY;
@property (nonatomic, strong) Bool* waitForRender;

- (double)maxDuration;
- (BOOL)hasAnimation;

@end
34 changes: 34 additions & 0 deletions lib/ios/RNNElementTransitionOptions.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#import "RNNElementTransitionOptions.h"

@implementation RNNElementTransitionOptions

- (instancetype)initWithDict:(NSDictionary *)dict {
self = [super init];

self.alpha = [[RNNAnimationConfigurationOptions alloc] initWithDict:dict[@"alpha"]];
self.x = [[RNNAnimationConfigurationOptions alloc] initWithDict:dict[@"x"]];
self.y = [[RNNAnimationConfigurationOptions alloc] initWithDict:dict[@"y"]];

return self;
}

- (BOOL)hasAnimation {
return self.x.hasAnimation || self.y.hasAnimation || self.alpha.hasAnimation;
}

- (double)maxDuration {
double maxDuration = 0;
if ([_x.duration getWithDefaultValue:0] > maxDuration) {
maxDuration = [_x.duration getWithDefaultValue:0];
}
if ([_y.duration getWithDefaultValue:0] > maxDuration) {
maxDuration = [_y.duration getWithDefaultValue:0];
}
if ([_alpha.duration getWithDefaultValue:0] > maxDuration) {
maxDuration = [_alpha.duration getWithDefaultValue:0];
}

return maxDuration;
}

@end
42 changes: 0 additions & 42 deletions lib/ios/RNNModalAnimation.m

This file was deleted.

21 changes: 16 additions & 5 deletions lib/ios/RNNModalManager.m
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#import "RNNModalManager.h"
#import "RNNRootViewController.h"
#import "RNNAnimationsTransitionDelegate.h"

@implementation RNNModalManager {
NSMutableArray* _pendingModalIdsToDismiss;
Expand All @@ -19,16 +20,17 @@ -(void)showModal:(UIViewController *)viewController animated:(BOOL)animated comp
[self showModal:viewController animated:animated hasCustomAnimation:NO completion:completion];
}

-(void)showModal:(UIViewController *)viewController animated:(BOOL)animated hasCustomAnimation:(BOOL)hasCustomAnimation completion:(RNNTransitionWithComponentIdCompletionBlock)completion {
-(void)showModal:(UIViewController<RNNLayoutProtocol> *)viewController animated:(BOOL)animated hasCustomAnimation:(BOOL)hasCustomAnimation completion:(RNNTransitionWithComponentIdCompletionBlock)completion {
if (!viewController) {
@throw [NSException exceptionWithName:@"ShowUnknownModal" reason:@"showModal called with nil viewController" userInfo:nil];
}

UIViewController* topVC = [self topPresentedVC];
topVC.definesPresentationContext = YES;

RNNAnimationsTransitionDelegate* tr = [[RNNAnimationsTransitionDelegate alloc] initWithScreenTransition:viewController.resolveOptions.animations.showModal isDismiss:NO];
if (hasCustomAnimation) {
viewController.transitioningDelegate = (UIViewController<UIViewControllerTransitioningDelegate>*)topVC;
viewController.transitioningDelegate = tr;
}

[topVC presentViewController:viewController animated:animated completion:^{
Expand Down Expand Up @@ -67,9 +69,9 @@ -(void)removePendingNextModalIfOnTop:(RNNTransitionCompletionBlock)completion {
}

UIViewController* topPresentedVC = [self topPresentedVC];

if ([options.animations.showModal hasCustomAnimation]) {
modalToDismiss.transitioningDelegate = modalToDismiss;
RNNAnimationsTransitionDelegate* tr = [[RNNAnimationsTransitionDelegate alloc] initWithScreenTransition:modalToDismiss.resolveOptions.animations.dismissModal isDismiss:YES];
if ([options.animations.dismissModal hasCustomAnimation]) {
[self topViewControllerParent:modalToDismiss].transitioningDelegate = tr;
}

if (modalToDismiss == topPresentedVC || [[topPresentedVC childViewControllers] containsObject:modalToDismiss]) {
Expand Down Expand Up @@ -115,5 +117,14 @@ -(UIViewController*)topPresentedVCLeaf {
return [root topViewController] ? [root topViewController] : root;
}

- (UIViewController *)topViewControllerParent:(UIViewController *)viewController {
UIViewController* topParent = viewController;
while (topParent.parentViewController) {
topParent = topParent.parentViewController;
}

return topParent;
}


@end
9 changes: 0 additions & 9 deletions lib/ios/RNNNavigationController.m
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@

#import "RNNNavigationController.h"
#import "RNNModalAnimation.h"
#import "RNNRootViewController.h"
#import "InteractivePopGestureDelegate.h"

Expand Down Expand Up @@ -107,14 +106,6 @@ - (UIViewController *)popViewControllerAnimated:(BOOL)animated {
return [super popViewControllerAnimated:animated];
}

- (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source {
return [[RNNModalAnimation alloc] initWithScreenTransition:self.getCurrentChild.resolveOptions.animations.showModal isDismiss:NO];
}

- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed {
return [[RNNModalAnimation alloc] initWithScreenTransition:self.getCurrentChild.resolveOptions.animations.dismissModal isDismiss:YES];
}

- (UIViewController *)getCurrentChild {
return ((UIViewController<RNNParentProtocol>*)self.topViewController);
}
Expand Down
8 changes: 4 additions & 4 deletions lib/ios/RNNNavigationOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
#import "RNNTopTabOptions.h"
#import "RNNTopTabsOptions.h"
#import "RNNOverlayOptions.h"
#import "RNNAnimationOptions.h"
#import "RNNTransitionsOptions.h"
#import "RNNSharedElementAnimationOptions.h"
#import "RNNAnimationsOptions.h"
#import "RNNStatusBarOptions.h"
#import "RNNPreviewOptions.h"
#import "RNNLayoutOptions.h"
Expand All @@ -24,8 +24,8 @@ extern const NSInteger TOP_BAR_TRANSPARENT_TAG;
@property (nonatomic, strong) RNNTopTabOptions* topTab;
@property (nonatomic, strong) RNNSideMenuOptions* sideMenu;
@property (nonatomic, strong) RNNOverlayOptions* overlay;
@property (nonatomic, strong) RNNAnimationOptions* customTransition;
@property (nonatomic, strong) RNNTransitionsOptions* animations;
@property (nonatomic, strong) RNNSharedElementAnimationOptions* customTransition;
@property (nonatomic, strong) RNNAnimationsOptions* animations;
@property (nonatomic, strong) RNNStatusBarOptions* statusBar;
@property (nonatomic, strong) RNNPreviewOptions* preview;
@property (nonatomic, strong) RNNLayoutOptions* layout;
Expand Down
4 changes: 2 additions & 2 deletions lib/ios/RNNNavigationOptions.m
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ - (instancetype)initWithDict:(NSDictionary *)dict {
self.sideMenu = [[RNNSideMenuOptions alloc] initWithDict:dict[@"sideMenu"]];
self.splitView = [[RNNSplitViewOptions alloc] initWithDict:dict[@"splitView"]];
self.overlay = [[RNNOverlayOptions alloc] initWithDict:dict[@"overlay"]];
self.customTransition = [[RNNAnimationOptions alloc] initWithDict:dict[@"customTransition"]];
self.animations = [[RNNTransitionsOptions alloc] initWithDict:dict[@"animations"]];
self.customTransition = [[RNNSharedElementAnimationOptions alloc] initWithDict:dict[@"customTransition"]];
self.animations = [[RNNAnimationsOptions alloc] initWithDict:dict[@"animations"]];
self.statusBar = [[RNNStatusBarOptions alloc] initWithDict:dict[@"statusBar"]];
self.preview = [[RNNPreviewOptions alloc] initWithDict:dict[@"preview"]];
self.layout = [[RNNLayoutOptions alloc] initWithDict:dict[@"layout"]];
Expand Down
6 changes: 4 additions & 2 deletions lib/ios/RNNPushAnimation.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "RNNModalAnimation.h"
#import "RNNScreenTransition.h"

@interface RNNPushAnimation : RNNModalAnimation <UIViewControllerAnimatedTransitioning>
@interface RNNPushAnimation : NSObject <UIViewControllerAnimatedTransitioning>

@property (nonatomic, strong) RNNScreenTransition* screenTransition;

- (instancetype)initWithScreenTransition:(RNNScreenTransition *)screenTransition;

Expand Down
Loading

0 comments on commit a98f187

Please sign in to comment.