Created
June 3, 2014 22:03
-
-
Save andyshep/282107c2c02a9ad36c67 to your computer and use it in GitHub Desktop.
A slide-and-zoom animation using collections views
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import <Foundation/Foundation.h> | |
#import "PASConstants.h" | |
#import "PASViewController.h" | |
@interface PASHideDetailAnimator : NSObject <UIViewControllerAnimatedTransitioning> | |
@end | |
@implementation PASHideDetailAnimator | |
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext { | |
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]; | |
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; | |
UICollectionView *fromCollectionView = [(UICollectionViewController *)fromViewController collectionView]; | |
UICollectionView *toCollectionView = [(UICollectionViewController *)toViewController collectionView]; | |
UIView *containerView = [transitionContext containerView]; | |
[containerView addSubview:toViewController.view]; | |
[fromViewController.view setAlpha:0.0f]; | |
CGRect originRect = [self originRectFromContext:transitionContext]; | |
CGRect destinationRect = [self destinationRectFromContext:transitionContext]; | |
destinationRect = [containerView convertRect:destinationRect fromView:toCollectionView]; | |
CGRect firstRect = CGRectMake(originRect.origin.x, originRect.origin.y, originRect.size.width, destinationRect.size.height); | |
CGRect secondRect = destinationRect; | |
UIEdgeInsets insets = UIEdgeInsetsMake(68.0f, 0.0f, 5.0f, 0.0f); | |
CGRect snapshotRect = CGRectMake(originRect.origin.x, originRect.origin.y, originRect.size.width, destinationRect.size.height); | |
UIView *snapshot = [fromCollectionView resizableSnapshotViewFromRect:snapshotRect afterScreenUpdates:NO withCapInsets:insets]; | |
[snapshot setFrame:[containerView convertRect:originRect fromView:fromCollectionView]]; | |
[containerView addSubview:snapshot]; | |
[UIView animateKeyframesWithDuration:PASPassAnimationDuration delay:0.0f options:0 animations:^{ | |
[UIView addKeyframeWithRelativeStartTime:0.0f relativeDuration:0.33f animations:^{ | |
[snapshot setFrame:[containerView convertRect:firstRect fromView:fromCollectionView]]; | |
}]; | |
[UIView addKeyframeWithRelativeStartTime:0.33f relativeDuration:0.33f animations:^{ | |
[snapshot setFrame:secondRect]; | |
}]; | |
[UIView addKeyframeWithRelativeStartTime:0.66f relativeDuration:0.33f animations:^{ | |
[toViewController.view setAlpha:1.0f]; | |
}]; | |
} completion:^(BOOL finished) { | |
[transitionContext completeTransition:finished]; | |
[fromViewController.view removeFromSuperview]; | |
[snapshot removeFromSuperview]; | |
}]; | |
} | |
- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext { | |
return PASPassAnimationDuration; | |
} | |
- (CGRect)originRectFromContext:(id<UIViewControllerContextTransitioning>)transitionContext { | |
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]; | |
if ([fromViewController isKindOfClass:[UICollectionViewController class]]) { | |
UICollectionView *collectionView = [(UICollectionViewController *)fromViewController collectionView]; | |
NSIndexPath *indexPath = [[collectionView indexPathsForVisibleItems] firstObject]; | |
UICollectionViewLayoutAttributes *attributes = [collectionView layoutAttributesForItemAtIndexPath:indexPath]; | |
return CGRectInset(attributes.frame, 15.0f, 0.0f); | |
} | |
return CGRectZero; | |
} | |
- (CGRect)destinationRectFromContext:(id<UIViewControllerContextTransitioning>)transitionContext { | |
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; | |
if ([toViewController isKindOfClass:[PASViewController class]]) { | |
UICollectionView *collectionView = [(PASViewController *)toViewController collectionView]; | |
// NSIndexPath *indexPath = [(PASViewController *)toViewController animationIndexPath]; | |
NSIndexPath *indexPath = [self originIndexPathFromContext:transitionContext]; | |
UICollectionViewLayoutAttributes *attributes = [collectionView layoutAttributesForItemAtIndexPath:indexPath]; | |
return attributes.frame; | |
} | |
return CGRectZero; | |
} | |
- (NSIndexPath *)originIndexPathFromContext:(id<UIViewControllerContextTransitioning>)transitionContext { | |
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]; | |
if ([fromViewController isKindOfClass:[UICollectionViewController class]]) { | |
UICollectionView *collectionView = [(UICollectionViewController *)fromViewController collectionView]; | |
NSIndexPath *indexPath = [[collectionView indexPathsForVisibleItems] firstObject]; | |
return indexPath; | |
} | |
return nil; | |
} | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import <Foundation/Foundation.h> | |
#import "PASConstants.h" | |
@interface PASShowDetailAnimator : NSObject <UIViewControllerAnimatedTransitioning> | |
@end | |
@implementation PASShowDetailAnimator | |
- (id)init { | |
if ((self = [super init])) { | |
// | |
} | |
return self; | |
} | |
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext { | |
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]; | |
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; | |
UICollectionView *fromCollectionView = [(UICollectionViewController *)fromViewController collectionView]; | |
// UICollectionView *toCollectionView = [(UICollectionViewController *)toViewController collectionView]; | |
UIView *containerView = [transitionContext containerView]; | |
[containerView setBackgroundColor:[UIColor darkGrayColor]]; | |
[toViewController.view setAlpha:0.0f]; | |
[containerView addSubview:toViewController.view]; | |
CGRect originRect = [self originRectFromContext:transitionContext]; | |
CGRect destinationRect = CGRectMake(15.0f, 105.0f, 290.0f, 422.0f); | |
CGRect firstRect = CGRectMake(destinationRect.origin.x, destinationRect.origin.y, destinationRect.size.width, originRect.size.height); | |
CGRect secondRect = CGRectMake(destinationRect.origin.x, destinationRect.origin.y, destinationRect.size.width, destinationRect.size.height); | |
UIEdgeInsets insets = UIEdgeInsetsMake(80.0f, 0.0f, 5.0f, 0.0f); | |
UIView *snapshot = [fromCollectionView resizableSnapshotViewFromRect:originRect afterScreenUpdates:NO withCapInsets:insets]; | |
[snapshot setFrame:[containerView convertRect:originRect fromView:fromCollectionView]]; | |
[containerView addSubview:snapshot]; | |
[UIView animateKeyframesWithDuration:PASPassAnimationDuration delay:0.0f options:0 animations:^{ | |
[UIView addKeyframeWithRelativeStartTime:0.0f relativeDuration:0.33f animations:^{ | |
[fromViewController.view setAlpha:0.0f]; | |
}]; | |
[UIView addKeyframeWithRelativeStartTime:0.33f relativeDuration:0.33f animations:^{ | |
[snapshot setFrame:firstRect]; | |
}]; | |
[UIView addKeyframeWithRelativeStartTime:0.66f relativeDuration:0.33f animations:^{ | |
[snapshot setFrame:secondRect]; | |
}]; | |
} completion:^(BOOL finished) { | |
[transitionContext completeTransition:finished]; | |
[toViewController.view setAlpha:1.0f]; | |
[fromViewController.view removeFromSuperview]; | |
[containerView addSubview:toViewController.view]; | |
[snapshot removeFromSuperview]; | |
}]; | |
} | |
- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext { | |
return PASPassAnimationDuration; | |
} | |
- (CGRect)originRectFromContext:(id<UIViewControllerContextTransitioning>)transitionContext { | |
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]; | |
if ([fromViewController isKindOfClass:[UICollectionViewController class]]) { | |
UICollectionView *collectionView = [(UICollectionViewController *)fromViewController collectionView]; | |
NSIndexPath *indexPath = [[collectionView indexPathsForSelectedItems] firstObject]; | |
UICollectionViewLayoutAttributes *attributes = [collectionView layoutAttributesForItemAtIndexPath:indexPath]; | |
return attributes.frame; | |
} | |
return CGRectZero; | |
} | |
- (CGRect)destinationRectFromContext:(id<UIViewControllerContextTransitioning>)transitionContext { | |
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; | |
if ([toViewController isKindOfClass:[UICollectionViewController class]]) { | |
UICollectionView *collectionView = [(UICollectionViewController *)toViewController collectionView]; | |
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0]; | |
UICollectionViewLayoutAttributes *attributes = [collectionView layoutAttributesForItemAtIndexPath:indexPath]; | |
return attributes.frame; | |
} | |
return CGRectZero; | |
} | |
- (NSArray *)snapshotFramesFromContext:(id<UIViewControllerContextTransitioning>)transitionContext { | |
__block NSMutableArray *frames = [NSMutableArray array]; | |
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]; | |
if ([fromViewController isKindOfClass:[UICollectionViewController class]]) { | |
UICollectionView *collectionView = [(UICollectionViewController *)fromViewController collectionView]; | |
NSMutableSet *mutableSet = [NSMutableSet setWithArray:[collectionView indexPathsForVisibleItems]]; | |
[mutableSet minusSet:[NSSet setWithArray:[collectionView indexPathsForSelectedItems]]]; | |
[[mutableSet allObjects] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { | |
NSIndexPath *indexPath = (NSIndexPath *)obj; | |
UICollectionViewLayoutAttributes *attributes = [collectionView layoutAttributesForItemAtIndexPath:indexPath]; | |
[frames addObject:[NSValue valueWithCGRect:attributes.frame]]; | |
}]; | |
} | |
return [NSArray arrayWithArray:frames]; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment