OLD | NEW |
| (Empty) |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 // ====== New Architecture ===== | |
6 // = This code is only used in the new iOS Chrome architecture. = | |
7 // ============================================================================ | |
8 | |
9 #import "ios/chrome/browser/ui/animators/zoom_transition_animator.h" | |
10 | |
11 #include "base/mac/foundation_util.h" | |
12 | |
13 #if !defined(__has_feature) || !__has_feature(objc_arc) | |
14 #error "This file requires ARC support." | |
15 #endif | |
16 | |
17 @implementation ZoomTransitionAnimator | |
18 @synthesize presenting = _presenting; | |
19 @synthesize presentationKey = _presentationKey; | |
20 @synthesize delegate = _delegate; | |
21 | |
22 #pragma mark - Public API | |
23 | |
24 - (void)selectDelegate:(NSArray<id<NSObject>>*)possibleDelegates { | |
25 for (id<NSObject> obj in possibleDelegates) { | |
26 if ([obj conformsToProtocol:@protocol(ZoomTransitionDelegate)]) { | |
27 self.delegate = static_cast<id<ZoomTransitionDelegate>>(obj); | |
28 return; | |
29 } | |
30 } | |
31 self.delegate = nil; | |
32 } | |
33 | |
34 #pragma mark - UIViewControllerAnimatedTransitioning | |
35 | |
36 - (void)animateTransition:(id<UIViewControllerContextTransitioning>)context { | |
37 UIView* presentedView; | |
38 UIView* presentingView; | |
39 UIViewController* presentedViewController; | |
40 UIViewController* presentingViewController; | |
41 | |
42 // Map the keyed view/view controllers in |context| to local vars. | |
43 if (self.presenting) { | |
44 presentedView = [context viewForKey:UITransitionContextToViewKey]; | |
45 presentingView = [context viewForKey:UITransitionContextFromViewKey]; | |
46 presentedViewController = | |
47 [context viewControllerForKey:UITransitionContextToViewControllerKey]; | |
48 presentingViewController = | |
49 [context viewControllerForKey:UITransitionContextFromViewControllerKey]; | |
50 } else { | |
51 presentedView = [context viewForKey:UITransitionContextFromViewKey]; | |
52 presentingView = [context viewForKey:UITransitionContextToViewKey]; | |
53 presentedViewController = | |
54 [context viewControllerForKey:UITransitionContextFromViewControllerKey]; | |
55 presentingViewController = | |
56 [context viewControllerForKey:UITransitionContextToViewControllerKey]; | |
57 } | |
58 | |
59 // Figure out what to use as the "zoom rectangle" -- the rectangle that the | |
60 // presentation or dismissal will move from or to. | |
61 CGRect rect = CGRectNull; | |
62 UIView* zoomRectView = presentingViewController.view; | |
63 if (self.delegate) { | |
64 rect = [self.delegate rectForZoomWithKey:self.presentationKey | |
65 inView:zoomRectView]; | |
66 } | |
67 | |
68 // If no usable rectangle was provided, use a rectangle that's 1/5 of the | |
69 // presenting view's smaller dimension square, positioned in its center. | |
70 if (CGRectIsNull(rect)) { | |
71 CGRect presenterRect = zoomRectView.bounds; | |
72 CGFloat side = std::min(CGRectGetHeight(presenterRect), | |
73 CGRectGetWidth(presenterRect)) / | |
74 5.0; | |
75 | |
76 rect = CGRectMake(CGRectGetMidX(presenterRect) - (side / 2.0), | |
77 CGRectGetMidY(presenterRect) - (side / 2.0), side, side); | |
78 } | |
79 | |
80 // Convert that rect into the coordinate space of the container view. | |
81 CGRect zoomRect = | |
82 [context.containerView convertRect:rect fromView:zoomRectView]; | |
83 | |
84 // Set up initial and final values for the animation. | |
85 CGFloat finalAlpha; | |
86 CGRect finalRect; | |
87 if (self.presenting) { | |
88 // In this case, the view being presented isn't yet in a view hierarchy, so | |
89 // it should be added in its initial position (|zoomRect|) and opacity. | |
90 presentedView.frame = zoomRect; | |
91 [context.containerView addSubview:presentedView]; | |
92 presentedView.alpha = 0.0; | |
93 // The presented view will finish the animation at the frame vended by | |
94 // |context|, at full opacity. | |
95 finalAlpha = 1.0; | |
96 finalRect = [context finalFrameForViewController:presentedViewController]; | |
97 } else { | |
98 // When dismissing, the presented view is already covering the window; | |
99 // the presenting view needs to be added underneath it (at the frame vended | |
100 // by |context|. | |
101 presentingView.frame = | |
102 [context finalFrameForViewController:presentingViewController]; | |
103 [context.containerView insertSubview:presentingView | |
104 belowSubview:presentedView]; | |
105 // The presented view will end up faded out, located at |zoomRect|. | |
106 finalAlpha = 0.0; | |
107 finalRect = zoomRect; | |
108 } | |
109 | |
110 [UIView animateWithDuration:[self transitionDuration:context] | |
111 animations:^{ | |
112 presentedView.frame = finalRect; | |
113 presentedView.alpha = finalAlpha; | |
114 [presentedView layoutIfNeeded]; | |
115 } | |
116 completion:^(BOOL finished) { | |
117 if (finished && !self.presenting) { | |
118 [presentedView removeFromSuperview]; | |
119 } | |
120 [context completeTransition:finished]; | |
121 }]; | |
122 } | |
123 | |
124 - (NSTimeInterval)transitionDuration: | |
125 (id<UIViewControllerContextTransitioning>)context { | |
126 return 0.35; | |
127 } | |
128 | |
129 @end | |
OLD | NEW |