From 27756b1e578cb8be3fa6d727a3aefafe9b1aa496 Mon Sep 17 00:00:00 2001 From: featherless Date: Fri, 25 Aug 2017 06:38:14 -0400 Subject: [PATCH] Add some organization to the transition examples. (#36) * Add some organization to the transition examples. Grouping the examples together by related functionality and feature. * Fix bug in presentation example. --- examples/CustomPresentationExample.swift | 2 + examples/FadeExample.m | 50 ++++------------- examples/FadeExample.swift | 42 +------------- examples/NavControllerFadeExample.swift | 38 ------------- .../project.pbxproj | 39 ++++++++++--- examples/transitions/FadeTransition.swift | 56 +++++++++++++++++++ 6 files changed, 101 insertions(+), 126 deletions(-) create mode 100644 examples/transitions/FadeTransition.swift diff --git a/examples/CustomPresentationExample.swift b/examples/CustomPresentationExample.swift index 7bab6ef..a72fb58 100644 --- a/examples/CustomPresentationExample.swift +++ b/examples/CustomPresentationExample.swift @@ -25,6 +25,8 @@ class CustomPresentationExampleViewController: ExampleTableViewController { override init(style: UITableViewStyle) { super.init(style: style) + transitions = [] + // Aside: we're using a simple model pattern here to define the data for the different // transitions up separate from their presentation. Check out the `didSelectRowAt` // implementation to see how we're ultimately presenting the modal view controller. diff --git a/examples/FadeExample.m b/examples/FadeExample.m index 799164f..3f494d9 100644 --- a/examples/FadeExample.m +++ b/examples/FadeExample.m @@ -18,20 +18,25 @@ #import "TransitionsCatalog-Swift.h" -// This example demonstrates the minimal path to building a custom transition using the Material -// Motion Transitioning APIs in Objective-C. Please see the companion Swift implementation for -// detailed comments. - -@interface FadeTransition : NSObject -@end +// This example demonstrates the minimal path to using a custom transition in Objective-C. @implementation FadeExampleObjcViewController - (void)didTap { ModalViewController *viewController = [[ModalViewController alloc] init]; + // The transition controller is an associated object on all UIViewController instances that + // allows you to customize the way the view controller is presented. The primary API on the + // controller that you'll make use of is the `transition` property. Setting this property will + // dictate how the view controller is presented. For this example we've built a custom + // FadeTransition, so we'll make use of that now: viewController.mdm_transitionController.transition = [[FadeTransition alloc] init]; + // Note that once we assign the transition object to the view controller, the transition will + // govern all subsequent presentations and dismissals of that view controller instance. If we + // want to use a different transition (e.g. to use an edge-swipe-to-dismiss transition) then we + // can simply change the transition object before initiating the transition. + [self presentViewController:viewController animated:true completion:nil]; } @@ -57,36 +62,3 @@ - (void)viewDidLoad { } @end - -@implementation FadeTransition - -- (NSTimeInterval)transitionDurationWithContext:(nonnull id)context { - return 0.3; -} - -- (void)startWithContext:(id)context { - [CATransaction begin]; - [CATransaction setCompletionBlock:^{ - [context transitionDidEnd]; - }]; - - CABasicAnimation *fade = [CABasicAnimation animationWithKeyPath:@"opacity"]; - - fade.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; - - fade.fromValue = @0; - fade.toValue = @1; - - if (context.direction == MDMTransitionDirectionBackward) { - id swap = fade.fromValue; - fade.fromValue = fade.toValue; - fade.toValue = swap; - } - - [context.foreViewController.view.layer addAnimation:fade forKey:fade.keyPath]; - [context.foreViewController.view.layer setValue:fade.toValue forKey:fade.keyPath]; - - [CATransaction commit]; -} - -@end diff --git a/examples/FadeExample.swift b/examples/FadeExample.swift index 460bfda..1324d3e 100644 --- a/examples/FadeExample.swift +++ b/examples/FadeExample.swift @@ -17,8 +17,8 @@ import UIKit import MotionTransitioning -// This example demonstrates the minimal path to building a custom transition using the Motion -// Transitioning APIs in Swift. The essential steps have been documented below. +// This example demonstrates the minimal path to using a custom transition in Swift. See +// FadeTransition.swift for the custom transition implementation. class FadeExampleViewController: ExampleViewController { @@ -59,41 +59,3 @@ class FadeExampleViewController: ExampleViewController { instructions: "Tap to present a modal transition.") } } - -// Transitions must be NSObject types that conform to the Transition protocol. -private final class FadeTransition: NSObject, Transition { - - // The sole method we're expected to implement, start is invoked each time the view controller is - // presented or dismissed. - func start(with context: TransitionContext) { - CATransaction.begin() - - CATransaction.setCompletionBlock { - // Let UIKit know that the transition has come to an end. - context.transitionDidEnd() - } - - let fade = CABasicAnimation(keyPath: "opacity") - - fade.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) - - // Define our animation assuming that we're going forward (presenting)... - fade.fromValue = 0 - fade.toValue = 1 - - // ...and reverse it if we're going backwards (dismissing). - if context.direction == .backward { - let swap = fade.fromValue - fade.fromValue = fade.toValue - fade.toValue = swap - } - - // Add the animation... - context.foreViewController.view.layer.add(fade, forKey: fade.keyPath) - - // ...and ensure that our model layer reflects the final value. - context.foreViewController.view.layer.setValue(fade.toValue, forKeyPath: fade.keyPath!) - - CATransaction.commit() - } -} diff --git a/examples/NavControllerFadeExample.swift b/examples/NavControllerFadeExample.swift index ddeedfa..6525613 100644 --- a/examples/NavControllerFadeExample.swift +++ b/examples/NavControllerFadeExample.swift @@ -75,41 +75,3 @@ class NavControllerFadeExampleViewController: ExampleViewController { instructions: "Tap to present a modal transition.") } } - -// Transitions must be NSObject types that conform to the Transition protocol. -private final class FadeTransition: NSObject, Transition { - - // The sole method we're expected to implement, start is invoked each time the view controller is - // presented or dismissed. - func start(with context: TransitionContext) { - CATransaction.begin() - - CATransaction.setCompletionBlock { - // Let UIKit know that the transition has come to an end. - context.transitionDidEnd() - } - - let fade = CABasicAnimation(keyPath: "opacity") - - fade.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) - - // Define our animation assuming that we're going forward (presenting)... - fade.fromValue = 0 - fade.toValue = 1 - - // ...and reverse it if we're going backwards (dismissing). - if context.direction == .backward { - let swap = fade.fromValue - fade.fromValue = fade.toValue - fade.toValue = swap - } - - // Add the animation... - context.foreViewController.view.layer.add(fade, forKey: fade.keyPath) - - // ...and ensure that our model layer reflects the final value. - context.foreViewController.view.layer.setValue(fade.toValue, forKeyPath: fade.keyPath!) - - CATransaction.commit() - } -} diff --git a/examples/apps/Catalog/TransitionsCatalog.xcodeproj/project.pbxproj b/examples/apps/Catalog/TransitionsCatalog.xcodeproj/project.pbxproj index d052675..201b5dc 100644 --- a/examples/apps/Catalog/TransitionsCatalog.xcodeproj/project.pbxproj +++ b/examples/apps/Catalog/TransitionsCatalog.xcodeproj/project.pbxproj @@ -18,6 +18,7 @@ 667A3F491DEE269400CB3A99 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 667A3F481DEE269400CB3A99 /* Assets.xcassets */; }; 667A3F4C1DEE269400CB3A99 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 667A3F4A1DEE269400CB3A99 /* LaunchScreen.storyboard */; }; 667A3F541DEE273000CB3A99 /* TableOfContents.swift in Sources */ = {isa = PBXBuildFile; fileRef = 667A3F531DEE273000CB3A99 /* TableOfContents.swift */; }; + 668E28851F4F5389008A4550 /* FadeTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 668E28841F4F5389008A4550 /* FadeTransition.swift */; }; 66A320FC1F1E716600E2EAC3 /* NavControllerFadeExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 664CC3D91F1E6F3000B80804 /* NavControllerFadeExample.swift */; }; 66BBC75E1ED37DAD0015CB9B /* FadeExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66BBC75D1ED37DAD0015CB9B /* FadeExample.swift */; }; 66BBC76D1ED4C8790015CB9B /* ExampleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66BBC7691ED4C8790015CB9B /* ExampleViewController.swift */; }; @@ -57,7 +58,7 @@ 6629151F1ED5E137002B9A5D /* ModalViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ModalViewController.swift; sourceTree = ""; }; 662915211ED5F222002B9A5D /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../../../README.md; sourceTree = ""; }; 662915221ED64A10002B9A5D /* TransitionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransitionTests.swift; sourceTree = ""; }; - 664CC3D91F1E6F3000B80804 /* NavControllerFadeExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavControllerFadeExample.swift; sourceTree = ""; }; + 664CC3D91F1E6F3000B80804 /* NavControllerFadeExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = NavControllerFadeExample.swift; path = ../NavControllerFadeExample.swift; sourceTree = ""; }; 666FAA801D384A6B000363DA /* TransitionsCatalog.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TransitionsCatalog.app; sourceTree = BUILT_PRODUCTS_DIR; }; 666FAA831D384A6B000363DA /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = Catalog/AppDelegate.swift; sourceTree = ""; }; 666FAA8A1D384A6B000363DA /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; @@ -71,14 +72,15 @@ 667A3F4B1DEE269400CB3A99 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 667A3F4D1DEE269400CB3A99 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 667A3F531DEE273000CB3A99 /* TableOfContents.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableOfContents.swift; sourceTree = ""; }; - 66BBC75D1ED37DAD0015CB9B /* FadeExample.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FadeExample.swift; sourceTree = ""; }; + 668E28841F4F5389008A4550 /* FadeTransition.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FadeTransition.swift; sourceTree = ""; }; + 66BBC75D1ED37DAD0015CB9B /* FadeExample.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = FadeExample.swift; path = ../FadeExample.swift; sourceTree = ""; }; 66BBC7691ED4C8790015CB9B /* ExampleViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExampleViewController.swift; sourceTree = ""; }; 66BBC76A1ED4C8790015CB9B /* ExampleViews.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExampleViews.swift; sourceTree = ""; }; 66BBC76B1ED4C8790015CB9B /* HexColor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HexColor.swift; sourceTree = ""; }; 66BBC76C1ED4C8790015CB9B /* Layout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Layout.swift; sourceTree = ""; }; 66BBC7711ED728DB0015CB9B /* TransitionWithPresentationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransitionWithPresentationTests.swift; sourceTree = ""; }; - 66BBC7731ED729A70015CB9B /* FadeExample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FadeExample.h; sourceTree = ""; }; - 66BBC7741ED729A70015CB9B /* FadeExample.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FadeExample.m; sourceTree = ""; }; + 66BBC7731ED729A70015CB9B /* FadeExample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FadeExample.h; path = ../FadeExample.h; sourceTree = ""; }; + 66BBC7741ED729A70015CB9B /* FadeExample.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FadeExample.m; path = ../FadeExample.m; sourceTree = ""; }; 738D98979677D88D24513391 /* Pods-TransitionsCatalog.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TransitionsCatalog.debug.xcconfig"; path = "../../../Pods/Target Support Files/Pods-TransitionsCatalog/Pods-TransitionsCatalog.debug.xcconfig"; sourceTree = ""; }; D7BB2931AFCEE4C91AE92E5D /* Pods-UnitTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-UnitTests.release.xcconfig"; path = "../../../Pods/Target Support Files/Pods-UnitTests/Pods-UnitTests.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -169,12 +171,9 @@ 666FAAA31D384B13000363DA /* examples */ = { isa = PBXGroup; children = ( - 66BBC75D1ED37DAD0015CB9B /* FadeExample.swift */, - 6629151D1ED5E0E0002B9A5D /* CustomPresentationExample.swift */, - 66BBC7731ED729A70015CB9B /* FadeExample.h */, - 66BBC7741ED729A70015CB9B /* FadeExample.m */, + 668E28831F4F5371008A4550 /* Fade transition */, + 668E28861F4F66C7008A4550 /* Custom presentation */, 072A063A1EEE26A900B9B5FC /* MenuExample.swift */, - 664CC3D91F1E6F3000B80804 /* NavControllerFadeExample.swift */, ); name = examples; path = ../..; @@ -218,6 +217,27 @@ path = ../TestHarness; sourceTree = ""; }; + 668E28831F4F5371008A4550 /* Fade transition */ = { + isa = PBXGroup; + children = ( + 66BBC75D1ED37DAD0015CB9B /* FadeExample.swift */, + 66BBC7731ED729A70015CB9B /* FadeExample.h */, + 66BBC7741ED729A70015CB9B /* FadeExample.m */, + 664CC3D91F1E6F3000B80804 /* NavControllerFadeExample.swift */, + 668E28841F4F5389008A4550 /* FadeTransition.swift */, + ); + name = "Fade transition"; + path = transitions; + sourceTree = ""; + }; + 668E28861F4F66C7008A4550 /* Custom presentation */ = { + isa = PBXGroup; + children = ( + 6629151D1ED5E0E0002B9A5D /* CustomPresentationExample.swift */, + ); + name = "Custom presentation"; + sourceTree = ""; + }; 66BBC7681ED4C8790015CB9B /* supplemental */ = { isa = PBXGroup; children = ( @@ -486,6 +506,7 @@ 6629151E1ED5E0E0002B9A5D /* CustomPresentationExample.swift in Sources */, 66BBC76E1ED4C8790015CB9B /* ExampleViews.swift in Sources */, 662915201ED5E137002B9A5D /* ModalViewController.swift in Sources */, + 668E28851F4F5389008A4550 /* FadeTransition.swift in Sources */, 66BBC75E1ED37DAD0015CB9B /* FadeExample.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/examples/transitions/FadeTransition.swift b/examples/transitions/FadeTransition.swift new file mode 100644 index 0000000..620d279 --- /dev/null +++ b/examples/transitions/FadeTransition.swift @@ -0,0 +1,56 @@ +/* + Copyright 2017-present The Material Motion Authors. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +import UIKit +import MotionTransitioning + +// Transitions must be NSObject types that conform to the Transition protocol. +final class FadeTransition: NSObject, Transition { + + // The sole method we're expected to implement, start is invoked each time the view controller is + // presented or dismissed. + func start(with context: TransitionContext) { + CATransaction.begin() + + CATransaction.setCompletionBlock { + // Let UIKit know that the transition has come to an end. + context.transitionDidEnd() + } + + let fade = CABasicAnimation(keyPath: "opacity") + + fade.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) + + // Define our animation assuming that we're going forward (presenting)... + fade.fromValue = 0 + fade.toValue = 1 + + // ...and reverse it if we're going backwards (dismissing). + if context.direction == .backward { + let swap = fade.fromValue + fade.fromValue = fade.toValue + fade.toValue = swap + } + + // Add the animation... + context.foreViewController.view.layer.add(fade, forKey: fade.keyPath) + + // ...and ensure that our model layer reflects the final value. + context.foreViewController.view.layer.setValue(fade.toValue, forKeyPath: fade.keyPath!) + + CATransaction.commit() + } +}