/
CGZDropAndRotateTransitionAnimator.m
executable file
·147 lines (110 loc) · 5.21 KB
/
CGZDropAndRotateTransitionAnimator.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
//
// CGZDropAndRotateTransitionAnimator.m
//
// Created by CarlosGz on 14/03/14.
// Copyright (c) 2014 CarlosGz. All rights reserved.
//
#import "CGZDropAndRotateTransitionAnimator.h"
#import "CGZDropAndRotateBehavior.h"
static NSTimeInterval const kAnimatedTransitionDuration = 0.5f;
@interface CGZDropAndRotateTransitionAnimator ()
@property (nonatomic, strong) UIDynamicAnimator *animator;
@end
@implementation CGZDropAndRotateTransitionAnimator
#pragma mark - UIViewControllerAnimatedTransitioning Protocol
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext
{
if (self.isPresenting) {
[self startEntryPresentation:transitionContext];
} else {
[self startDismissalPresentation:transitionContext];
}
}
- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext
{
return kAnimatedTransitionDuration;
}
#pragma mark - Custom Accessors
- (UIDynamicAnimator *)animator
{
if (!_animator) {
_animator = [[UIDynamicAnimator alloc] initWithReferenceView:[[UIApplication sharedApplication] windows][0]];
}
return _animator;
}
- (CGFloat)yAxisPositionCorrection
{
if (!_yAxisPositionCorrection) {
_yAxisPositionCorrection = 1.0;
}
return _yAxisPositionCorrection;
}
#pragma mark - Private
- (void) startEntryPresentation:(id<UIViewControllerContextTransitioning>)transitionContext
{
UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
fromVC.view.userInteractionEnabled = NO;
//[transitionContext.containerView addSubview:fromVC.view];
[transitionContext.containerView addSubview:toVC.view];
/// The toVC should start presenting at the center of the fromVC
CGRect startFrame = [self startPresentingFrameFromViewController:fromVC
toTheViewController:toVC];
/// The toVC should end presenting at the center of the FromVC frame with an optional custom "y" position
CGRect endFrame = [self endPresentingFrameFromViewController:fromVC
toTheViewController:toVC];
toVC.view.frame = startFrame;
[UIView animateWithDuration:1.0
delay:0.0
usingSpringWithDamping:0.5
initialSpringVelocity:0.8
options:UIViewAnimationOptionCurveEaseInOut
animations:^{
toVC.view.frame = endFrame;
} completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
}];
}
/** Calculate the initial position of the toVC in the fromVC
* The initial position will be at the top and the center of the fromVC
* @param fromVC the current VC, the origin of the presentation
* @param toVC the destination VC of the presentation
* @return CGrect with the location and dimentions of the destination VC
*/
-(CGRect)startPresentingFrameFromViewController:(UIViewController *)fromVC
toTheViewController:(UIViewController *)toVC
{
CGRect aRect = [toVC.view.subviews[0] frame];
aRect.origin.x = fromVC.view.center.x - ([toVC.view.subviews[0] frame].size.width / 2);
aRect.origin.y = 0;
return aRect;
}
/** Calculate the final position of the toVC in the fromVC
* the final position will be at the center of the fromVC's coordinate axis
* @param fromVC the current VC, the origin of the presentation
* @param toVC the destination VC of the presentation
* @return CGRect with the location and dimentions of the center of the destination VC
*/
-(CGRect)endPresentingFrameFromViewController:(UIViewController *)fromVC
toTheViewController:(UIViewController *)toVC
{
CGRect aRect = [toVC.view.subviews[0] frame];
aRect.origin.x = fromVC.view.center.x - ([toVC.view.subviews[0] frame].size.width / 2);
aRect.origin.y = fromVC.view.center.y - ([toVC.view.subviews[0] frame].size.height / 2) * self.yAxisPositionCorrection;
return aRect;
}
- (void) startDismissalPresentation:(id<UIViewControllerContextTransitioning>)transitionContext
{
UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
toVC.view.userInteractionEnabled = YES;
CGZDropAndRotateBehavior *dropAndRotateBehavior = [[CGZDropAndRotateBehavior alloc]initWithItem:fromVC.view];
[self.animator addBehavior:dropAndRotateBehavior];
double delayInSeconds = [self transitionDuration:transitionContext];
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^{
[transitionContext completeTransition:YES];
[dropAndRotateBehavior removeItem:fromVC.view];
});
}
@end