Skip to content
This repository has been archived by the owner on Aug 13, 2021. It is now read-only.

Commit

Permalink
Allow transition types to be instantiated and stored on the transitio…
Browse files Browse the repository at this point in the history
…n controller.

Summary: This makes it possible to configure a transition's behavior.

Reviewers: O2 Material Motion, O4 Material Apple platform reviewers, #material_motion, randcode-generator

Reviewed By: randcode-generator

Tags: #material_motion

Differential Revision: http://codereview.cc/D3199
  • Loading branch information
Jeff Verkoeyen committed May 11, 2017
1 parent 235a3e7 commit 5b6149d
Show file tree
Hide file tree
Showing 9 changed files with 35 additions and 41 deletions.
4 changes: 1 addition & 3 deletions examples/ContextualTransitionExample.swift
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ class PhotoAlbumViewController: UIViewController, UICollectionViewDataSource, UI

super.init(nibName: nil, bundle: nil)

transitionController.transitionType = PushBackTransition.self
transitionController.transition = PushBackTransition()
}

required init?(coder aDecoder: NSCoder) {
Expand Down Expand Up @@ -258,8 +258,6 @@ class PhotoAlbumViewController: UIViewController, UICollectionViewDataSource, UI

private class PushBackTransition: Transition {

required init() {}

func willBeginTransition(withContext ctx: TransitionContext, runtime: MotionRuntime) -> [Stateful] {
let foreVC = ctx.fore as! PhotoAlbumViewController
let foreImageView = (foreVC.collectionView.cellForItem(at: foreVC.indexPathForCurrentPhoto()) as! PhotoCollectionViewCell).imageView
Expand Down
9 changes: 4 additions & 5 deletions examples/FabTransitionExample.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class FabTransitionExampleViewController: ExampleViewController, TransitionConte

func didTap() {
let vc = ModalViewController()
vc.transitionController.transitionType = CircularRevealTransition.self
vc.transitionController.transition = CircularRevealTransition()
present(vc, animated: true)
}

Expand Down Expand Up @@ -76,18 +76,17 @@ private class ModalViewController: UIViewController {

let floodFillOvershootRatio: CGFloat = 1.2

private class CircularRevealTransition: Transition {
private class CircularRevealTransition: TransitionWithTermination {

// TODO: Support for transient views.
var floodFillView: UIView!
var foreViewLayer: CALayer!
deinit {

func didEndTransition(withContext ctx: TransitionContext, runtime: MotionRuntime) {
floodFillView.removeFromSuperview()
foreViewLayer.mask = nil
}

required init() {}

func willBeginTransition(withContext ctx: TransitionContext, runtime: MotionRuntime) -> [Stateful] {
foreViewLayer = ctx.fore.view.layer

Expand Down
4 changes: 1 addition & 3 deletions examples/InteractivePushBackTransitionExample.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ private class ModalViewController: UIViewController, UIGestureRecognizerDelegate
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)

transitionController.transitionType = PushBackTransition.self
transitionController.transition = PushBackTransition()
}

required init?(coder aDecoder: NSCoder) {
Expand Down Expand Up @@ -72,8 +72,6 @@ private class ModalViewController: UIViewController, UIGestureRecognizerDelegate

private class PushBackTransition: Transition {

required init() {}

func willBeginTransition(withContext ctx: TransitionContext, runtime: MotionRuntime) -> [Stateful] {
let draggable = Draggable(withFirstGestureIn: ctx.gestureRecognizers)

Expand Down
6 changes: 2 additions & 4 deletions examples/ModalDialogExample.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class ModalDialogViewController: UIViewController {
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)

transitionController.transitionType = ModalDialogTransition.self
transitionController.transition = ModalDialogTransition()
preferredContentSize = .init(width: 200, height: 200)
modalPresentationStyle = .overCurrentContext
}
Expand All @@ -69,8 +69,6 @@ class ModalDialogViewController: UIViewController {

class ModalDialogTransition: SelfDismissingTransition {

required init() {}

func willBeginTransition(withContext ctx: TransitionContext, runtime: MotionRuntime) -> [Stateful] {
let size = ctx.fore.view.frame.size
let bounds = ctx.containerView().bounds
Expand Down Expand Up @@ -106,7 +104,7 @@ class ModalDialogTransition: SelfDismissingTransition {
return [tossable.spring]
}

static func willPresent(fore: UIViewController, dismisser: ViewControllerDismisser) {
func willPresent(fore: UIViewController, dismisser: ViewControllerDismisser) {
let tap = UITapGestureRecognizer()
fore.view.addGestureRecognizer(tap)
dismisser.dismissWhenGestureRecognizerBegins(tap)
Expand Down
4 changes: 1 addition & 3 deletions examples/PushBackTransitionExample.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ private class ModalViewController: UIViewController {
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)

transitionController.transitionType = PushBackTransition.self
transitionController.transition = PushBackTransition()
}

required init?(coder aDecoder: NSCoder) {
Expand All @@ -67,8 +67,6 @@ private class ModalViewController: UIViewController {

private class PushBackTransition: Transition {

required init() {}

func willBeginTransition(withContext ctx: TransitionContext, runtime: MotionRuntime) -> [Stateful] {
let bounds = ctx.containerView().bounds
let backPosition = bounds.maxY + ctx.fore.view.bounds.height / 2
Expand Down
2 changes: 1 addition & 1 deletion examples/StickerPickerExample.swift
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ private class StickerListViewController: UICollectionViewController {
init() {
super.init(collectionViewLayout: UICollectionViewFlowLayout())

transitionController.transitionType = ModalTransition.self
transitionController.transition = ModalTransition()

modalPresentationStyle = .overCurrentContext
}
Expand Down
15 changes: 7 additions & 8 deletions src/transitions/Transition.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ import Foundation
import UIKit

/**
An object that is capable of responding to a transition that is about to begin.
A transition is responsible for describing the motion that will occur during a UIViewController
transition.
*/
public protocol WillBeginTransition {

public protocol Transition {
/**
Invoked on initiation of a view controller transition.

Expand All @@ -34,12 +34,11 @@ public protocol WillBeginTransition {
A transition is responsible for describing the motion that will occur during a UIViewController
transition.
*/
public protocol Transition: WillBeginTransition {

public protocol TransitionWithTermination: Transition {
/**
Transitions must be instantiable.
Invoked on completion of a view controller transition.
*/
init()
func didEndTransition(withContext ctx: TransitionContext, runtime: MotionRuntime)
}

/**
Expand Down Expand Up @@ -68,5 +67,5 @@ public protocol TransitionWithPresentation: Transition {
cause the presented view controller to be dismissed.
*/
public protocol SelfDismissingTransition: Transition {
static func willPresent(fore: UIViewController, dismisser: ViewControllerDismisser)
func willPresent(fore: UIViewController, dismisser: ViewControllerDismisser)
}
10 changes: 7 additions & 3 deletions src/transitions/TransitionContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public final class TransitionContext: NSObject {

weak var delegate: TransitionDelegate?

init(transitionType: Transition.Type,
init(transition: Transition,
direction: TransitionDirection,
back: UIViewController,
fore: UIViewController,
Expand All @@ -108,7 +108,7 @@ public final class TransitionContext: NSObject {
self.window = TransitionTimeWindow(duration: TransitionContext.defaultDuration)
self.presentationController = presentationController

self.transition = transitionType.init()
self.transition = transition

super.init()
}
Expand Down Expand Up @@ -178,7 +178,7 @@ extension TransitionContext {

var terminators = transition.willBeginTransition(withContext: self, runtime: self.runtime)

if let presentationController = presentationController as? WillBeginTransition {
if let presentationController = presentationController as? Transition {
terminators.append(contentsOf: presentationController.willBeginTransition(withContext: self,
runtime: self.runtime))
}
Expand Down Expand Up @@ -251,6 +251,10 @@ extension TransitionContext {
}
context.completeTransition(completedInOriginalDirection)

if let transitionWithTermination = transition as? TransitionWithTermination {
transitionWithTermination.didEndTransition(withContext: self, runtime: runtime)
}

runtime = nil
transition = nil

Expand Down
22 changes: 11 additions & 11 deletions src/transitions/TransitionController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,9 @@ public final class TransitionController {

Must be a subclass of MDMTransition.
*/
public var transitionType: Transition.Type? {
set { _transitioningDelegate.transitionType = newValue }
get { return _transitioningDelegate.transitionType }
public var transition: Transition? {
set { _transitioningDelegate.transition = newValue }
get { return _transitioningDelegate.transition }
}

/**
Expand Down Expand Up @@ -164,7 +164,7 @@ private final class TransitioningDelegate: NSObject, UIViewControllerTransitioni
}

var ctx: TransitionContext?
var transitionType: Transition.Type?
var transition: Transition?

let dismisser: ViewControllerDismisser
let gestureDelegate = GestureDelegate()
Expand All @@ -183,12 +183,12 @@ private final class TransitioningDelegate: NSObject, UIViewControllerTransitioni
}
assert(ctx == nil, "A transition is already active.")

if let transitionType = transitionType {
if direction == .forward, let selfDismissingDirector = transitionType as? SelfDismissingTransition.Type {
if let transition = transition {
if direction == .forward, let selfDismissingDirector = transition as? SelfDismissingTransition {
selfDismissingDirector.willPresent(fore: fore, dismisser: dismisser)
}

ctx = TransitionContext(transitionType: transitionType,
ctx = TransitionContext(transition: transition,
direction: direction,
back: back,
fore: fore,
Expand Down Expand Up @@ -245,15 +245,15 @@ private final class TransitioningDelegate: NSObject, UIViewControllerTransitioni
}

func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
guard let transitionWithPresentation = transitionType as? TransitionWithPresentation.Type else {
guard let transitionWithPresentation = transition as? TransitionWithPresentation else {
return nil
}
if let presentationController = presentationController {
return presentationController
}
presentationController = transitionWithPresentation.presentationController(forPresented: presented,
presenting: presenting,
source: source)
presentationController = type(of: transitionWithPresentation).presentationController(forPresented: presented,
presenting: presenting,
source: source)
return presentationController
}
}
Expand Down

0 comments on commit 5b6149d

Please sign in to comment.