Skip to content

Commit 8e9d9b9

Browse files
committed
新增snapkit和一部分Custom Presentation代码
1 parent 062da5c commit 8e9d9b9

42 files changed

Lines changed: 3540 additions & 5 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CustomTransition/CustomTransition-Swift/CustomTransition-Swift.xcodeproj/project.pbxproj

Lines changed: 98 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10+
9B34A0F01C6AD7FC0085D279 /* CustomPresentationFirstViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B34A0EF1C6AD7FC0085D279 /* CustomPresentationFirstViewController.swift */; };
11+
9B34A0F21C6AD8370085D279 /* CustomPresentationSecondViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B34A0F11C6AD8370085D279 /* CustomPresentationSecondViewController.swift */; };
12+
9B34A0F41C6AD85D0085D279 /* CustomPresentationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B34A0F31C6AD85D0085D279 /* CustomPresentationController.swift */; };
1013
9B5074F91C671E4A00C89416 /* CrossDissolveFirstViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B5074F81C671E4A00C89416 /* CrossDissolveFirstViewController.swift */; };
1114
9B5074FB1C68403000C89416 /* CrossDissolveSecondViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B5074FA1C68403000C89416 /* CrossDissolveSecondViewController.swift */; };
1215
9B5074FF1C6843CE00C89416 /* UIViewShortHand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B5074FE1C6843CE00C89416 /* UIViewShortHand.swift */; };
@@ -24,6 +27,7 @@
2427
9B5CEE0C1C66D44E003D0D6F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9B5CEE0A1C66D44E003D0D6F /* LaunchScreen.storyboard */; };
2528
9B5CEE171C66D44F003D0D6F /* CustomTransition_SwiftTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B5CEE161C66D44F003D0D6F /* CustomTransition_SwiftTests.swift */; };
2629
9B5CEE221C66D44F003D0D6F /* CustomTransition_SwiftUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B5CEE211C66D44F003D0D6F /* CustomTransition_SwiftUITests.swift */; };
30+
9D51D2AFFDE101469A248793 /* Pods.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7BFF32D2745BC524127B1052 /* Pods.framework */; };
2731
/* End PBXBuildFile section */
2832

2933
/* Begin PBXContainerItemProxy section */
@@ -44,6 +48,11 @@
4448
/* End PBXContainerItemProxy section */
4549

4650
/* Begin PBXFileReference section */
51+
7BFF32D2745BC524127B1052 /* Pods.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods.framework; sourceTree = BUILT_PRODUCTS_DIR; };
52+
895BA2A0ACB38F3741EB2DB5 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = "<group>"; };
53+
9B34A0EF1C6AD7FC0085D279 /* CustomPresentationFirstViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomPresentationFirstViewController.swift; sourceTree = "<group>"; };
54+
9B34A0F11C6AD8370085D279 /* CustomPresentationSecondViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomPresentationSecondViewController.swift; sourceTree = "<group>"; };
55+
9B34A0F31C6AD85D0085D279 /* CustomPresentationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomPresentationController.swift; sourceTree = "<group>"; };
4756
9B5074F81C671E4A00C89416 /* CrossDissolveFirstViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CrossDissolveFirstViewController.swift; sourceTree = "<group>"; };
4857
9B5074FA1C68403000C89416 /* CrossDissolveSecondViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CrossDissolveSecondViewController.swift; sourceTree = "<group>"; };
4958
9B5074FE1C6843CE00C89416 /* UIViewShortHand.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIViewShortHand.swift; sourceTree = "<group>"; };
@@ -67,13 +76,15 @@
6776
9B5CEE1D1C66D44F003D0D6F /* CustomTransition-SwiftUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "CustomTransition-SwiftUITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
6877
9B5CEE211C66D44F003D0D6F /* CustomTransition_SwiftUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomTransition_SwiftUITests.swift; sourceTree = "<group>"; };
6978
9B5CEE231C66D44F003D0D6F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
79+
EB54B1CB285AD7D45738DED6 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = "<group>"; };
7080
/* End PBXFileReference section */
7181

7282
/* Begin PBXFrameworksBuildPhase section */
7383
9B5CEDFB1C66D44E003D0D6F /* Frameworks */ = {
7484
isa = PBXFrameworksBuildPhase;
7585
buildActionMask = 2147483647;
7686
files = (
87+
9D51D2AFFDE101469A248793 /* Pods.framework in Frameworks */,
7788
);
7889
runOnlyForDeploymentPostprocessing = 0;
7990
};
@@ -94,6 +105,25 @@
94105
/* End PBXFrameworksBuildPhase section */
95106

96107
/* Begin PBXGroup section */
108+
0B7B075FEB8B2A16ED5EC0C9 /* Pods */ = {
109+
isa = PBXGroup;
110+
children = (
111+
EB54B1CB285AD7D45738DED6 /* Pods.debug.xcconfig */,
112+
895BA2A0ACB38F3741EB2DB5 /* Pods.release.xcconfig */,
113+
);
114+
name = Pods;
115+
sourceTree = "<group>";
116+
};
117+
9B34A0EE1C6AD7800085D279 /* Custom Presentation */ = {
118+
isa = PBXGroup;
119+
children = (
120+
9B34A0EF1C6AD7FC0085D279 /* CustomPresentationFirstViewController.swift */,
121+
9B34A0F11C6AD8370085D279 /* CustomPresentationSecondViewController.swift */,
122+
9B34A0F31C6AD85D0085D279 /* CustomPresentationController.swift */,
123+
);
124+
path = "Custom Presentation";
125+
sourceTree = "<group>";
126+
};
97127
9B5074F71C671E2200C89416 /* Cross Dissolve */ = {
98128
isa = PBXGroup;
99129
children = (
@@ -125,6 +155,8 @@
125155
9B5CEE151C66D44F003D0D6F /* CustomTransition-SwiftTests */,
126156
9B5CEE201C66D44F003D0D6F /* CustomTransition-SwiftUITests */,
127157
9B5CEDFF1C66D44E003D0D6F /* Products */,
158+
0B7B075FEB8B2A16ED5EC0C9 /* Pods */,
159+
C7F759BD514A0EA847D4763B /* Frameworks */,
128160
);
129161
sourceTree = "<group>";
130162
};
@@ -143,8 +175,9 @@
143175
children = (
144176
9B5CEE011C66D44E003D0D6F /* AppDelegate.swift */,
145177
9B5CEE031C66D44E003D0D6F /* ViewController.swift */,
146-
9B5075081C68D91900C89416 /* Interactivity */,
147178
9B5074F71C671E2200C89416 /* Cross Dissolve */,
179+
9B5075081C68D91900C89416 /* Interactivity */,
180+
9B34A0EE1C6AD7800085D279 /* Custom Presentation */,
148181
9B5074FE1C6843CE00C89416 /* UIViewShortHand.swift */,
149182
9B5CEE051C66D44E003D0D6F /* Main.storyboard */,
150183
9B5CEE081C66D44E003D0D6F /* Assets.xcassets */,
@@ -172,16 +205,27 @@
172205
path = "CustomTransition-SwiftUITests";
173206
sourceTree = "<group>";
174207
};
208+
C7F759BD514A0EA847D4763B /* Frameworks */ = {
209+
isa = PBXGroup;
210+
children = (
211+
7BFF32D2745BC524127B1052 /* Pods.framework */,
212+
);
213+
name = Frameworks;
214+
sourceTree = "<group>";
215+
};
175216
/* End PBXGroup section */
176217

177218
/* Begin PBXNativeTarget section */
178219
9B5CEDFD1C66D44E003D0D6F /* CustomTransition-Swift */ = {
179220
isa = PBXNativeTarget;
180221
buildConfigurationList = 9B5CEE261C66D44F003D0D6F /* Build configuration list for PBXNativeTarget "CustomTransition-Swift" */;
181222
buildPhases = (
223+
52039C198AFCA9C2D9CDABB1 /* Check Pods Manifest.lock */,
182224
9B5CEDFA1C66D44E003D0D6F /* Sources */,
183225
9B5CEDFB1C66D44E003D0D6F /* Frameworks */,
184226
9B5CEDFC1C66D44E003D0D6F /* Resources */,
227+
FBDE29327038F4A7FD5F1D59 /* Embed Pods Frameworks */,
228+
3355480DCC46F9AAD30F44BC /* Copy Pods Resources */,
185229
);
186230
buildRules = (
187231
);
@@ -301,17 +345,68 @@
301345
};
302346
/* End PBXResourcesBuildPhase section */
303347

348+
/* Begin PBXShellScriptBuildPhase section */
349+
3355480DCC46F9AAD30F44BC /* Copy Pods Resources */ = {
350+
isa = PBXShellScriptBuildPhase;
351+
buildActionMask = 2147483647;
352+
files = (
353+
);
354+
inputPaths = (
355+
);
356+
name = "Copy Pods Resources";
357+
outputPaths = (
358+
);
359+
runOnlyForDeploymentPostprocessing = 0;
360+
shellPath = /bin/sh;
361+
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n";
362+
showEnvVarsInLog = 0;
363+
};
364+
52039C198AFCA9C2D9CDABB1 /* Check Pods Manifest.lock */ = {
365+
isa = PBXShellScriptBuildPhase;
366+
buildActionMask = 2147483647;
367+
files = (
368+
);
369+
inputPaths = (
370+
);
371+
name = "Check Pods Manifest.lock";
372+
outputPaths = (
373+
);
374+
runOnlyForDeploymentPostprocessing = 0;
375+
shellPath = /bin/sh;
376+
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
377+
showEnvVarsInLog = 0;
378+
};
379+
FBDE29327038F4A7FD5F1D59 /* Embed Pods Frameworks */ = {
380+
isa = PBXShellScriptBuildPhase;
381+
buildActionMask = 2147483647;
382+
files = (
383+
);
384+
inputPaths = (
385+
);
386+
name = "Embed Pods Frameworks";
387+
outputPaths = (
388+
);
389+
runOnlyForDeploymentPostprocessing = 0;
390+
shellPath = /bin/sh;
391+
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-frameworks.sh\"\n";
392+
showEnvVarsInLog = 0;
393+
};
394+
/* End PBXShellScriptBuildPhase section */
395+
304396
/* Begin PBXSourcesBuildPhase section */
305397
9B5CEDFA1C66D44E003D0D6F /* Sources */ = {
306398
isa = PBXSourcesBuildPhase;
307399
buildActionMask = 2147483647;
308400
files = (
309401
9B5074FF1C6843CE00C89416 /* UIViewShortHand.swift in Sources */,
402+
9B34A0F21C6AD8370085D279 /* CustomPresentationSecondViewController.swift in Sources */,
310403
9B5074FB1C68403000C89416 /* CrossDissolveSecondViewController.swift in Sources */,
311404
9B5CEE041C66D44E003D0D6F /* ViewController.swift in Sources */,
312405
9B5074F91C671E4A00C89416 /* CrossDissolveFirstViewController.swift in Sources */,
313406
9B5075101C68EC8C00C89416 /* InteractivityTransitionAnimator.swift in Sources */,
407+
9B34A0F01C6AD7FC0085D279 /* CustomPresentationFirstViewController.swift in Sources */,
314408
9B50750C1C68D95600C89416 /* InteractivitySecondViewController.swift in Sources */,
409+
9B34A0F41C6AD85D0085D279 /* CustomPresentationController.swift in Sources */,
315410
9B5075051C68982400C89416 /* CrossDissolveAnimator.swift in Sources */,
316411
9B5CEE021C66D44E003D0D6F /* AppDelegate.swift in Sources */,
317412
9B5075071C68CBE800C89416 /* HalfWaySpringAnimator.swift in Sources */,
@@ -455,6 +550,7 @@
455550
};
456551
9B5CEE271C66D44F003D0D6F /* Debug */ = {
457552
isa = XCBuildConfiguration;
553+
baseConfigurationReference = EB54B1CB285AD7D45738DED6 /* Pods.debug.xcconfig */;
458554
buildSettings = {
459555
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
460556
INFOPLIST_FILE = "CustomTransition-Swift/Info.plist";
@@ -466,6 +562,7 @@
466562
};
467563
9B5CEE281C66D44F003D0D6F /* Release */ = {
468564
isa = XCBuildConfiguration;
565+
baseConfigurationReference = 895BA2A0ACB38F3741EB2DB5 /* Pods.release.xcconfig */;
469566
buildSettings = {
470567
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
471568
INFOPLIST_FILE = "CustomTransition-Swift/Info.plist";
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
//
2+
// CustomPresentationController.swift
3+
// CustomTransition-Swift
4+
//
5+
// Created by 张星宇 on 16/2/10.
6+
// Copyright © 2016年 zxy. All rights reserved.
7+
//
8+
9+
import UIKit
10+
11+
class CustomPresentationController: UIPresentationController, UIViewControllerTransitioningDelegate, UIViewControllerAnimatedTransitioning {
12+
13+
let CORNER_RADIUS: CGFloat = 16
14+
var presentationWrappingView: UIView? = nil
15+
var dimmingView: UIView? = nil
16+
17+
override init(presentedViewController: UIViewController, presentingViewController: UIViewController) {
18+
super.init(presentedViewController: presentedViewController, presentingViewController: presentingViewController)
19+
20+
presentedViewController.modalPresentationStyle = .Custom
21+
}
22+
23+
override func presentationTransitionWillBegin() {
24+
let presentedViewControllerView = super.presentedView()
25+
let presentationWrapperView = UIView(frame: self.frameOfPresentedViewInContainerView())
26+
presentationWrapperView.layer.shadowOpacity = 0.44
27+
presentationWrapperView.layer.shadowRadius = 13
28+
presentationWrapperView.layer.shadowOffset = CGSizeMake(0, -6)
29+
self.presentationWrappingView = presentationWrapperView
30+
31+
let presentationRoundedCornerView = UIView(frame: UIEdgeInsetsInsetRect(presentationWrapperView.bounds, UIEdgeInsetsMake(0, 0, -CORNER_RADIUS, 0)))
32+
presentationRoundedCornerView.autoresizingMask = [UIViewAutoresizing.FlexibleHeight, UIViewAutoresizing.FlexibleWidth]
33+
presentationRoundedCornerView.layer.cornerRadius = CORNER_RADIUS
34+
presentationRoundedCornerView.layer.masksToBounds = true
35+
36+
let presentedViewControllerWrapperView = UIView(frame: UIEdgeInsetsInsetRect(presentationRoundedCornerView.bounds, UIEdgeInsetsMake(0, 0, CORNER_RADIUS, 0)))
37+
presentedViewControllerWrapperView.autoresizingMask = [UIViewAutoresizing.FlexibleWidth, UIViewAutoresizing.FlexibleHeight]
38+
39+
presentedViewControllerView?.autoresizingMask = [UIViewAutoresizing.FlexibleWidth, UIViewAutoresizing.FlexibleHeight]
40+
presentedViewControllerView?.frame = presentedViewControllerWrapperView.bounds
41+
presentedViewControllerWrapperView.addSubview(presentedViewControllerView!)
42+
presentationRoundedCornerView.addSubview(presentedViewControllerWrapperView)
43+
presentationWrapperView.addSubview(presentationRoundedCornerView)
44+
45+
let dimmingView = UIView(frame: (self.containerView?.bounds)!)
46+
dimmingView.backgroundColor = UIColor.blackColor()
47+
dimmingView.opaque = false
48+
dimmingView.autoresizingMask = [UIViewAutoresizing.FlexibleWidth, UIViewAutoresizing.FlexibleHeight]
49+
dimmingView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: Selector("dimmingViewTapped:")))
50+
self.dimmingView = dimmingView;
51+
self.containerView?.addSubview(dimmingView)
52+
53+
let transitionCoordinator = self.presentingViewController.transitionCoordinator()
54+
self.dimmingView?.alpha = 0
55+
transitionCoordinator?.animateAlongsideTransition({ (context: UIViewControllerTransitionCoordinatorContext) -> Void in
56+
self.dimmingView?.alpha = 0.5
57+
}, completion: nil)
58+
}
59+
60+
override func presentationTransitionDidEnd(completed: Bool) {
61+
if !completed {
62+
self.presentationWrappingView = nil
63+
self.dimmingView = nil
64+
}
65+
}
66+
67+
override func dismissalTransitionWillBegin() {
68+
let transitionCoordinator = self.presentingViewController.transitionCoordinator()
69+
transitionCoordinator?.animateAlongsideTransition({ (context: UIViewControllerTransitionCoordinatorContext) -> Void in
70+
self.dimmingView?.alpha = 0
71+
}, completion: nil)
72+
}
73+
74+
override func dismissalTransitionDidEnd(completed: Bool) {
75+
if completed {
76+
self.presentationWrappingView = nil
77+
self.dimmingView = nil
78+
}
79+
}
80+
}
81+
82+
83+
extension CustomPresentationController {
84+
func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
85+
if let isAnimated = transitionContext?.isAnimated() {
86+
return isAnimated ? 0.35 : 0
87+
}
88+
return 0
89+
}
90+
91+
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
92+
let fromViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)
93+
let toViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)
94+
let containerView = transitionContext.containerView()
95+
96+
let fromView = transitionContext.viewForKey(UITransitionContextFromViewKey)
97+
let toView = transitionContext.viewForKey(UITransitionContextToViewKey)
98+
let isPresenting = (self.presentingViewController == fromViewController)
99+
100+
let fromViewInitialFrame = transitionContext.initialFrameForViewController(fromViewController!)
101+
var fromViewFinalFrame = transitionContext.finalFrameForViewController(fromViewController!)
102+
var toViewInitialFrame = transitionContext.initialFrameForViewController(toViewController!)
103+
let toViewFinalFrame = transitionContext.finalFrameForViewController(toViewController!)
104+
105+
if toView != nil {
106+
containerView?.addSubview(toView!)
107+
}
108+
109+
if isPresenting {
110+
toViewInitialFrame.origin = CGPointMake(CGRectGetMinX(containerView!.bounds), CGRectGetMaxY(containerView!.bounds));
111+
toViewInitialFrame.size = toViewFinalFrame.size;
112+
toView?.frame = toViewInitialFrame;
113+
} else {
114+
// Because our presentation wraps the presented view controller's view
115+
// in an intermediate view hierarchy, it is more accurate to rely
116+
// on the current frame of fromView than fromViewInitialFrame as the
117+
// initial frame (though in this example they will be the same).
118+
fromViewFinalFrame = CGRectOffset(fromView!.frame, 0, CGRectGetHeight(fromView!.frame));
119+
}
120+
121+
let transitionDuration = self.transitionDuration(transitionContext)
122+
UIView.animateWithDuration(transitionDuration, animations: {
123+
if isPresenting {
124+
toView?.frame = toViewFinalFrame;
125+
}
126+
else {
127+
fromView?.frame = fromViewFinalFrame;
128+
}
129+
130+
}) { (finished: Bool) -> Void in
131+
let wasCancelled = transitionContext.transitionWasCancelled()
132+
transitionContext.completeTransition(!wasCancelled)
133+
}
134+
}
135+
}
136+
137+
// MARK: - 实现协议UIViewControllerTransitioningDelegate
138+
extension CustomPresentationController {
139+
func presentationControllerForPresentedViewController(presented: UIViewController, presentingViewController presenting: UIViewController, sourceViewController source: UIViewController) -> UIPresentationController? {
140+
return self
141+
}
142+
143+
func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
144+
return self
145+
}
146+
147+
func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
148+
return self
149+
}
150+
}

0 commit comments

Comments
 (0)