Skip to content

Commit c6234c5

Browse files
committed
初步实现交互式动画
1 parent f927001 commit c6234c5

5 files changed

Lines changed: 125 additions & 12 deletions

File tree

CustomTransition/CustomTransition-Swift/CustomTransition-Swift/Interactivity/InteractivityFirstViewController.swift

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ class InteractivityFirstViewController: UIViewController {
4040
interactiveTransitionRecognizer.edges = .Right;
4141
self.view.addGestureRecognizer(interactiveTransitionRecognizer)
4242

43+
/// 设置动画代理
44+
customTransitionDelegate.gestureRecognizer = interactiveTransitionRecognizer
45+
interactivitySecondViewController.transitioningDelegate = customTransitionDelegate
46+
interactivitySecondViewController.modalPresentationStyle = .FullScreen
47+
4348
}
4449

4550
override func didReceiveMemoryWarning() {
@@ -51,20 +56,14 @@ class InteractivityFirstViewController: UIViewController {
5156
extension InteractivityFirstViewController {
5257
func interactiveTransitionRecognizerAction(sender: UIScreenEdgePanGestureRecognizer) {
5358
if sender.state == .Began {
54-
customTransitionDelegate.gestureRecognizer = sender
55-
customTransitionDelegate.targetEdge = .Right
56-
interactivitySecondViewController.transitioningDelegate = customTransitionDelegate
57-
interactivitySecondViewController.modalPresentationStyle = .FullScreen
59+
5860
}
5961
}
60-
61-
func prepareForInteractiveTransition() {
62-
63-
}
6462
}
6563

6664
extension InteractivityFirstViewController {
6765
func animationButtonDidClicked() {
66+
customTransitionDelegate.targetEdge = .Right
6867
self.presentViewController(interactivitySecondViewController, animated: true, completion: nil)
6968
}
7069

CustomTransition/CustomTransition-Swift/CustomTransition-Swift/Interactivity/InteractivitySecondViewController.swift

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,16 @@ class InteractivitySecondViewController: UIViewController {
3030
button.setTitle("Dismiss", forState: .Normal)
3131
button.addTarget(self, action: Selector("buttonDidClicked"), forControlEvents: .TouchUpInside)
3232
view.addSubview(button)
33-
// Do any additional setup after loading the view.
33+
34+
/// 添加滑动交互手势
35+
let interactiveTransitionRecognizer = UIScreenEdgePanGestureRecognizer.init(target: self, action: Selector("interactiveTransitionRecognizerAction:"))
36+
interactiveTransitionRecognizer.edges = .Right;
37+
self.view.addGestureRecognizer(interactiveTransitionRecognizer)
38+
39+
/// 设置动画代理
40+
if let transitionDelegate = self.transitioningDelegate as? InteractivityTransitionDelegate {
41+
transitionDelegate.gestureRecognizer = interactiveTransitionRecognizer
42+
}
3443
}
3544

3645
override func didReceiveMemoryWarning() {
@@ -45,6 +54,9 @@ extension InteractivitySecondViewController {
4554
/**
4655
* 应该由FirstVC执行下面这行代码,为了保持demo简单,突出重点,这里的写法其实是不严格的,请见谅
4756
*/
57+
if let transitionDelegate = self.transitioningDelegate as? InteractivityTransitionDelegate {
58+
transitionDelegate.targetEdge = .Left
59+
}
4860
self.dismissViewControllerAnimated(true, completion: nil)
4961
}
5062
}

CustomTransition/CustomTransition-Swift/CustomTransition-Swift/Interactivity/InteractivityTransitionAnimator.swift

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,56 @@ class InteractivityTransitionAnimator: NSObject, UIViewControllerAnimatedTransit
2020
}
2121

2222
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
23+
let fromViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)
24+
let toViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)
25+
let containerView = transitionContext.containerView()
2326

27+
var fromView = fromViewController?.view
28+
var toView = toViewController?.view
29+
30+
if transitionContext.respondsToSelector(Selector("viewForKey:")) {
31+
fromView = transitionContext.viewForKey(UITransitionContextFromViewKey)
32+
toView = transitionContext.viewForKey(UITransitionContextToViewKey)
33+
}
34+
35+
let isPresenting = (toViewController?.presentingViewController == fromViewController)
36+
37+
let fromFrame = transitionContext.initialFrameForViewController(fromViewController!)
38+
let toFrame = transitionContext.finalFrameForViewController(toViewController!)
39+
40+
let offset: CGVector
41+
switch self.targetEdge {
42+
case UIRectEdge.Top: offset = CGVectorMake(0, 1)
43+
case UIRectEdge.Bottom: offset = CGVectorMake(0, -1)
44+
case UIRectEdge.Left: offset = CGVectorMake(1, 0)
45+
case UIRectEdge.Right: offset = CGVectorMake(-1, 0)
46+
default:fatalError("targetEdge must be one of UIRectEdgeTop, UIRectEdgeBottom, UIRectEdgeLeft, or UIRectEdgeRight.")
47+
}
48+
49+
if isPresenting {
50+
// For a presentation, the toView starts off-screen and slides in.
51+
fromView?.frame = fromFrame
52+
toView?.frame = CGRectOffset(toFrame, toFrame.size.width * offset.dx * -1,
53+
toFrame.size.height * offset.dy * -1)
54+
containerView?.addSubview(toView!)
55+
} else {
56+
fromView?.frame = fromFrame
57+
toView?.frame = toFrame
58+
containerView?.insertSubview(toView!, belowSubview: fromView!)
59+
}
60+
61+
UIView.animateWithDuration(self.transitionDuration(transitionContext), animations: { () -> Void in
62+
if isPresenting {
63+
toView?.frame = toFrame;
64+
} else {
65+
// For a dismissal, the fromView slides off the screen.
66+
fromView?.frame = CGRectOffset(fromFrame, fromFrame.size.width * offset.dx,
67+
fromFrame.size.height * offset.dy);
68+
}
69+
}) { (finished: Bool) -> Void in
70+
let wasCanceled = transitionContext.transitionWasCancelled()
71+
if wasCanceled {toView?.removeFromSuperview()}
72+
transitionContext.completeTransition(!wasCanceled)
73+
}
2474
}
2575
}

CustomTransition/CustomTransition-Swift/CustomTransition-Swift/Interactivity/InteractivityTransitionDelegate.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,16 @@ class InteractivityTransitionDelegate: NSObject, UIViewControllerTransitioningDe
2323
/// 前两个函数和淡入淡出demo中的实现一致
2424

2525
func interactionControllerForPresentation(animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
26-
if gestureRecognizer != nil {
27-
26+
if let gestureRecognizer = self.gestureRecognizer {
27+
return TransitionInteractionController(gestureRecognizer: gestureRecognizer, edgeForDragging: targetEdge)
2828
}
2929
return nil
3030
}
3131

3232
func interactionControllerForDismissal(animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
33+
if let gestureRecognizer = self.gestureRecognizer {
34+
return TransitionInteractionController(gestureRecognizer: gestureRecognizer, edgeForDragging: targetEdge)
35+
}
3336
return nil
3437
}
3538
}

CustomTransition/CustomTransition-Swift/CustomTransition-Swift/Interactivity/TransitionInteractionController.swift

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,54 @@
99
import UIKit
1010

1111
class TransitionInteractionController: UIPercentDrivenInteractiveTransition {
12-
12+
var transitionContext: UIViewControllerContextTransitioning? = nil
13+
var gestureRecognizer: UIScreenEdgePanGestureRecognizer
14+
var edge: UIRectEdge
15+
16+
init(gestureRecognizer: UIScreenEdgePanGestureRecognizer, edgeForDragging edge: UIRectEdge) {
17+
assert(edge == .Top || edge == .Bottom || edge == .Left || edge == .Right,
18+
"edgeForDragging must be one of UIRectEdgeTop, UIRectEdgeBottom, UIRectEdgeLeft, or UIRectEdgeRight.")
19+
self.gestureRecognizer = gestureRecognizer
20+
self.edge = edge
21+
22+
super.init()
23+
self.gestureRecognizer.addTarget(self, action: Selector("gestureRecognizeDidUpdate:"))
24+
}
25+
26+
override func startInteractiveTransition(transitionContext: UIViewControllerContextTransitioning) {
27+
self.transitionContext = transitionContext
28+
29+
super.startInteractiveTransition(transitionContext)
30+
}
31+
32+
private func percentForGesture(gesture: UIScreenEdgePanGestureRecognizer) -> CGFloat {
33+
let transitionContainerView = transitionContext?.containerView()
34+
let locationInSourceView = gesture.locationInView(transitionContainerView)
35+
36+
let width = transitionContainerView?.bounds.width
37+
let height = transitionContainerView?.bounds.height
38+
39+
switch self.edge {
40+
case UIRectEdge.Right: return (width! - locationInSourceView.x) / width!
41+
case UIRectEdge.Left: return locationInSourceView.x / width!
42+
case UIRectEdge.Bottom: return (height! - locationInSourceView.y) / height!
43+
case UIRectEdge.Top: return locationInSourceView.y / height!
44+
default: return 0
45+
}
46+
}
47+
48+
func gestureRecognizeDidUpdate(gestureRecognizer: UIScreenEdgePanGestureRecognizer) {
49+
switch gestureRecognizer.state {
50+
case .Began: break
51+
case .Changed: self.updateInteractiveTransition(self.percentForGesture(gestureRecognizer))
52+
case .Ended:
53+
if self.percentForGesture(gestureRecognizer) >= 0.5 {
54+
self.finishInteractiveTransition()
55+
}
56+
else {
57+
self.cancelInteractiveTransition()
58+
}
59+
default: self.cancelInteractiveTransition()
60+
}
61+
}
1362
}

0 commit comments

Comments
 (0)