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