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