XWCoolAnimator+XWFold.m 6.71 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
//
//  XWCoolAnimator+XWFold.m
//  XWTransitionDemo
//
//  Created by wazrx on 16/6/13.
//  Copyright © 2016年 wazrx. All rights reserved.
//

#import "XWCoolAnimator+XWFold.h"
#import "UIView+Snapshot.h"

@implementation XWCoolAnimator (XWFold)

- (void)xw_setFoldToAnimation:(id<UIViewControllerContextTransitioning>)transitionContext leftFlag:(BOOL)left {
    [self _xw_animation:transitionContext flag:left duration:self.toDuration];
    
}

- (void)xw_setFoldBackAnimation:(id<UIViewControllerContextTransitioning>)transitionContext leftFlag:(BOOL)left {
    [self _xw_animation:transitionContext flag:left duration:self.backDuration];
    
}

- (void)_xw_animation:(id<UIViewControllerContextTransitioning>)transitionContext flag:(BOOL)flag duration:(NSTimeInterval)duration{
    UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    UIView *toView = toVC.view;
    UIView *fromView = fromVC.view;
    UIView *containerView = [transitionContext containerView];
    toView.frame = [transitionContext finalFrameForViewController:toVC];
    toView.frame = CGRectOffset(toView.frame, toView.frame.size.width, 0);
    [containerView addSubview:toView];
    CATransform3D transform = CATransform3DIdentity;
    transform.m34 = -0.005;
    containerView.layer.sublayerTransform = transform;
    CGSize size = toView.frame.size;
    float foldWidth = size.width * 0.5 / (float)self.foldCount ;
    NSMutableArray* fromViewFolds = [NSMutableArray new];
    NSMutableArray* toViewFolds = [NSMutableArray new];
    UIImage *fromImage = fromView.snapshotImage;
    UIImage *toImage = toView.snapshotImage;
    for (int i=0 ;i<self.foldCount; i++){
        float offset = (float)i * foldWidth * 2;
        UIView *leftFromViewFold = [self _xw_createSnapshotFromView:fromView location:offset left:YES image:fromImage];
        leftFromViewFold.layer.position = CGPointMake(offset, size.height/2);
        [fromViewFolds addObject:leftFromViewFold];
        [leftFromViewFold.subviews[1] setAlpha:0.0];
        UIView *rightFromViewFold = [self _xw_createSnapshotFromView:fromView location:offset + foldWidth left:NO image:fromImage];
        rightFromViewFold.layer.position = CGPointMake(offset + foldWidth * 2, size.height/2);
        [fromViewFolds addObject:rightFromViewFold];
        [rightFromViewFold.subviews[1] setAlpha:0.0];
        UIView *leftToViewFold = [self _xw_createSnapshotFromView:toView location:offset left:YES image:toImage];
        leftToViewFold.layer.position = CGPointMake(!flag ? size.width : 0.0, size.height/2);
        leftToViewFold.layer.transform = CATransform3DMakeRotation(M_PI_2, 0.0, 1.0, 0.0);
        [toViewFolds addObject:leftToViewFold];
        UIView *rightToViewFold = [self _xw_createSnapshotFromView:toView location:offset + foldWidth left:NO image:toImage];
        rightToViewFold.layer.position = CGPointMake(!flag ? size.width : 0.0, size.height/2);
        rightToViewFold.layer.transform = CATransform3DMakeRotation(-M_PI_2, 0.0, 1.0, 0.0);
        [toViewFolds addObject:rightToViewFold];
    }
    fromView.frame = CGRectOffset(fromView.frame, fromView.frame.size.width, 0);
    [UIView animateWithDuration:duration animations:^{
        for (int i=0; i<self.foldCount; i++){
            float offset = (float)i * foldWidth * 2;
            UIView* leftFromView = fromViewFolds[i*2];
            leftFromView.layer.position = CGPointMake(!flag ? 0.0 : size.width, size.height/2);
            leftFromView.layer.transform = CATransform3DRotate(transform, M_PI_2, 0.0, 1.0, 0);
            [leftFromView.subviews[1] setAlpha:1.0];
            UIView* rightFromView = fromViewFolds[i*2+1];
            rightFromView.layer.position = CGPointMake(!flag ? 0.0 : size.width, size.height/2);
            rightFromView.layer.transform = CATransform3DRotate(transform, -M_PI_2, 0.0, 1.0, 0);
            [rightFromView.subviews[1] setAlpha:1.0];
            UIView* leftToView = toViewFolds[i*2];
            leftToView.layer.position = CGPointMake(offset, size.height/2);
            leftToView.layer.transform = CATransform3DIdentity;
            [leftToView.subviews[1] setAlpha:0.0];
            UIView* rightToView = toViewFolds[i*2+1];
            rightToView.layer.position = CGPointMake(offset + foldWidth * 2, size.height/2);
            rightToView.layer.transform = CATransform3DIdentity;
            [rightToView.subviews[1] setAlpha:0.0];
        }
    }  completion:^(BOOL finished) {
        for (UIView *view in toViewFolds) {
            [view removeFromSuperview];
        }
        for (UIView *view in fromViewFolds) {
            [view removeFromSuperview];
        }
        
        BOOL transitionFinished = ![transitionContext transitionWasCancelled];
        if (transitionFinished) {
            toView.frame = containerView.bounds;
            fromView.frame = containerView.bounds;
        }
        else {
            fromView.frame = containerView.bounds;
        }
        [transitionContext completeTransition:transitionFinished];
    }];
}
- (UIView *)_xw_createSnapshotFromView:(UIView *)view location:(CGFloat)offset left:(BOOL)left image:(UIImage *)image{
    
    CGSize size = view.frame.size;
    UIView *containerView = view.superview;
    float foldWidth = size.width * 0.5 / (float)self.foldCount ;
    UIView *snapshotView = [UIView new];
    CGRect snapshotRegion = CGRectMake(offset, 0.0, foldWidth, size.height);
    snapshotView.frame = snapshotRegion;
    snapshotView.contentImage = image;
    snapshotView.layer.contentsRect = CGRectMake(offset / size.width, 0.0, foldWidth / size.width, 1.0f);
    UIView* snapshotWithShadowView = [self _xw_addShadowToView:snapshotView reverse:left];
    [containerView addSubview:snapshotWithShadowView];
    snapshotWithShadowView.layer.anchorPoint = CGPointMake( left ? 0.0 : 1.0, 0.5);
    
    return snapshotWithShadowView;
}

- (UIView *)_xw_addShadowToView:(UIView*)view reverse:(BOOL)reverse {
    UIView* viewWithShadow = [[UIView alloc] initWithFrame:view.frame];
    UIView* shadowView = [[UIView alloc] initWithFrame:viewWithShadow.bounds];
    CAGradientLayer *gradient = [CAGradientLayer layer];
    gradient.frame = shadowView.bounds;
    gradient.colors = @[(id)[UIColor colorWithWhite:0.0 alpha:0.0].CGColor,
                        (id)[UIColor colorWithWhite:0.0 alpha:1.0].CGColor];
    gradient.startPoint = CGPointMake(reverse ? 0.0 : 1.0, reverse ? 0.2 : 0.0);
    gradient.endPoint = CGPointMake(reverse ? 1.0 : 0.0, reverse ? 0.0 : 1.0);
    [shadowView.layer insertSublayer:gradient atIndex:1];
    view.frame = view.bounds;
    [viewWithShadow addSubview:view];
    [viewWithShadow addSubview:shadowView];
    return viewWithShadow;
}

@end