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 |