Skip to content

Instantly share code, notes, and snippets.

@andyshep
Created June 3, 2014 22:03
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save andyshep/282107c2c02a9ad36c67 to your computer and use it in GitHub Desktop.
Save andyshep/282107c2c02a9ad36c67 to your computer and use it in GitHub Desktop.
A slide-and-zoom animation using collections views
#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
#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