Commit 4375ba87 by Daniel Dahan

reworked MotionTransitions

parent 19e673bf
......@@ -11,6 +11,8 @@
963150D21EE50DA6002B0D42 /* Motion+Obj-C.swift in Sources */ = {isa = PBXBuildFile; fileRef = 963150D11EE50DA6002B0D42 /* Motion+Obj-C.swift */; };
963150D61EE51C7A002B0D42 /* MotionAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 963150D41EE51C7A002B0D42 /* MotionAnimation.swift */; };
963150DA1EE51EB4002B0D42 /* MotionAnimationFillMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 963150D91EE51EB4002B0D42 /* MotionAnimationFillMode.swift */; };
966A7F091EEC422000A2DAAC /* MotionSnapshotType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 966A7F081EEC422000A2DAAC /* MotionSnapshotType.swift */; };
966A7F0B1EEC424000A2DAAC /* MotionCoordinateSpace.swift in Sources */ = {isa = PBXBuildFile; fileRef = 966A7F0A1EEC424000A2DAAC /* MotionCoordinateSpace.swift */; };
968989B91EE5B34B003B8F3D /* MotionHasInsertOrder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 968989B81EE5B34B003B8F3D /* MotionHasInsertOrder.swift */; };
968989DC1EE65F2B003B8F3D /* MotionPreprocessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 968989DB1EE65F2B003B8F3D /* MotionPreprocessor.swift */; };
968989DE1EE6633E003B8F3D /* MotionAnimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 968989DD1EE6633E003B8F3D /* MotionAnimator.swift */; };
......@@ -36,7 +38,7 @@
96AEB6A21EE4610F009A3BE0 /* MotionTransition+MotionStringConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96AEB67C1EE4610F009A3BE0 /* MotionTransition+MotionStringConvertible.swift */; };
96AEB6A31EE4610F009A3BE0 /* MotionPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96AEB67D1EE4610F009A3BE0 /* MotionPlugin.swift */; };
96AEB6A41EE4610F009A3BE0 /* MotionStringConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96AEB67E1EE4610F009A3BE0 /* MotionStringConvertible.swift */; };
96AEB6A51EE4610F009A3BE0 /* MotionTargetState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96AEB67F1EE4610F009A3BE0 /* MotionTargetState.swift */; };
96AEB6A51EE4610F009A3BE0 /* MotionTransitionState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96AEB67F1EE4610F009A3BE0 /* MotionTransitionState.swift */; };
96AEB6A61EE4610F009A3BE0 /* MotionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96AEB6801EE4610F009A3BE0 /* MotionViewController.swift */; };
96AEB6A71EE4610F009A3BE0 /* Lexer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96AEB6821EE4610F009A3BE0 /* Lexer.swift */; };
96AEB6A81EE4610F009A3BE0 /* Nodes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96AEB6831EE4610F009A3BE0 /* Nodes.swift */; };
......@@ -54,6 +56,8 @@
963150D11EE50DA6002B0D42 /* Motion+Obj-C.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Motion+Obj-C.swift"; sourceTree = "<group>"; };
963150D41EE51C7A002B0D42 /* MotionAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionAnimation.swift; sourceTree = "<group>"; };
963150D91EE51EB4002B0D42 /* MotionAnimationFillMode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MotionAnimationFillMode.swift; path = ../Extensions/MotionAnimationFillMode.swift; sourceTree = "<group>"; };
966A7F081EEC422000A2DAAC /* MotionSnapshotType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionSnapshotType.swift; sourceTree = "<group>"; };
966A7F0A1EEC424000A2DAAC /* MotionCoordinateSpace.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionCoordinateSpace.swift; sourceTree = "<group>"; };
968989B81EE5B34B003B8F3D /* MotionHasInsertOrder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionHasInsertOrder.swift; sourceTree = "<group>"; };
968989DB1EE65F2B003B8F3D /* MotionPreprocessor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionPreprocessor.swift; sourceTree = "<group>"; };
968989DD1EE6633E003B8F3D /* MotionAnimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionAnimator.swift; sourceTree = "<group>"; };
......@@ -79,7 +83,7 @@
96AEB67C1EE4610F009A3BE0 /* MotionTransition+MotionStringConvertible.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "MotionTransition+MotionStringConvertible.swift"; sourceTree = "<group>"; };
96AEB67D1EE4610F009A3BE0 /* MotionPlugin.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionPlugin.swift; sourceTree = "<group>"; };
96AEB67E1EE4610F009A3BE0 /* MotionStringConvertible.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionStringConvertible.swift; sourceTree = "<group>"; };
96AEB67F1EE4610F009A3BE0 /* MotionTargetState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionTargetState.swift; sourceTree = "<group>"; };
96AEB67F1EE4610F009A3BE0 /* MotionTransitionState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionTransitionState.swift; sourceTree = "<group>"; };
96AEB6801EE4610F009A3BE0 /* MotionViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionViewController.swift; sourceTree = "<group>"; };
96AEB6821EE4610F009A3BE0 /* Lexer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Lexer.swift; sourceTree = "<group>"; };
96AEB6831EE4610F009A3BE0 /* Nodes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Nodes.swift; sourceTree = "<group>"; };
......@@ -201,11 +205,13 @@
963150D41EE51C7A002B0D42 /* MotionAnimation.swift */,
96AEB6791EE4610F009A3BE0 /* MotionContext.swift */,
96AEB67A1EE4610F009A3BE0 /* MotionIndependentController.swift */,
966A7F081EEC422000A2DAAC /* MotionSnapshotType.swift */,
966A7F0A1EEC424000A2DAAC /* MotionCoordinateSpace.swift */,
96AEB67F1EE4610F009A3BE0 /* MotionTransitionState.swift */,
96AEB67B1EE4610F009A3BE0 /* MotionTransition.swift */,
96AEB67C1EE4610F009A3BE0 /* MotionTransition+MotionStringConvertible.swift */,
96AEB67D1EE4610F009A3BE0 /* MotionPlugin.swift */,
96AEB67E1EE4610F009A3BE0 /* MotionStringConvertible.swift */,
96AEB67F1EE4610F009A3BE0 /* MotionTargetState.swift */,
96AEB6801EE4610F009A3BE0 /* MotionViewController.swift */,
96E49A3F1EEA08F8006D5A93 /* MotionTransitionObserver.swift */,
96AEB6811EE4610F009A3BE0 /* Parser */,
......@@ -294,6 +300,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
966A7F0B1EEC424000A2DAAC /* MotionCoordinateSpace.swift in Sources */,
96AEB6A31EE4610F009A3BE0 /* MotionPlugin.swift in Sources */,
96AEB69A1EE4610F009A3BE0 /* Motion+UIView.swift in Sources */,
96AEB6AD1EE4610F009A3BE0 /* DurationPreprocessor.swift in Sources */,
......@@ -304,7 +311,7 @@
968989DE1EE6633E003B8F3D /* MotionAnimator.swift in Sources */,
96AEB6A21EE4610F009A3BE0 /* MotionTransition+MotionStringConvertible.swift in Sources */,
968989B91EE5B34B003B8F3D /* MotionHasInsertOrder.swift in Sources */,
96AEB6A51EE4610F009A3BE0 /* MotionTargetState.swift in Sources */,
96AEB6A51EE4610F009A3BE0 /* MotionTransitionState.swift in Sources */,
96AEB6961EE4610F009A3BE0 /* Motion+CAMediaTimingFunction.swift in Sources */,
96AEB6941EE4610F009A3BE0 /* Motion+Array.swift in Sources */,
96AEB6951EE4610F009A3BE0 /* Motion+CALayer.swift in Sources */,
......@@ -313,6 +320,7 @@
96AEB6921EE4610F009A3BE0 /* MotionDebugView.swift in Sources */,
96E49A401EEA08F8006D5A93 /* MotionTransitionObserver.swift in Sources */,
96AEB6A01EE4610F009A3BE0 /* MotionIndependentController.swift in Sources */,
966A7F091EEC422000A2DAAC /* MotionSnapshotType.swift in Sources */,
96AEB6AA1EE4610F009A3BE0 /* Regex.swift in Sources */,
96AEB6901EE4610F009A3BE0 /* MotionViewPropertyViewContext.swift in Sources */,
96AEB6991EE4610F009A3BE0 /* Motion+UIKit.swift in Sources */,
......
......@@ -68,8 +68,8 @@ public protocol MotionAnimator: class {
/**
Applies the given state to the given view.
- Parameter state: A MotionTargetState.
- Parameter state: A MotionTransitionState.
- Parameter to view: A UIView.
*/
func apply(state: MotionTargetState, to view: UIView)
func apply(state: MotionTransitionState, to view: UIView)
}
......@@ -39,7 +39,7 @@ internal class MotionAnimatorViewContext {
var duration: TimeInterval = 0
/// The animation target state.
var targetState: MotionTargetState
var targetState: MotionTransitionState
/// The computed current time of the snapshot layer.
var currentTime: TimeInterval {
......@@ -55,9 +55,9 @@ internal class MotionAnimatorViewContext {
An initializer.
- Parameter animator: A MotionAnimator.
- Parameter snapshot: A UIView.
- Parameter targetState: A MotionTargetState.
- Parameter targetState: A MotionTransitionState.
*/
required init(animator: MotionAnimator, snapshot: UIView, targetState: MotionTargetState) {
required init(animator: MotionAnimator, snapshot: UIView, targetState: MotionTransitionState) {
self.animator = animator
self.snapshot = snapshot
self.targetState = targetState
......@@ -72,11 +72,11 @@ internal class MotionAnimatorViewContext {
A class function that determines if a view can be animated
to a given state.
- Parameter view: A UIView.
- Parameter state: A MotionTargetState.
- Parameter state: A MotionTransitionState.
- Parameter isAppearing: A boolean that determines whether the
view is appearing.
*/
class func canAnimate(view: UIView, state: MotionTargetState, isAppearing: Bool) -> Bool {
class func canAnimate(view: UIView, state: MotionTransitionState, isAppearing: Bool) -> Bool {
return false
}
......@@ -97,9 +97,9 @@ internal class MotionAnimatorViewContext {
/**
Applies the given state to the target state.
- Parameter state: A MotionTargetState.
- Parameter state: A MotionTransitionState.
*/
func apply(state: MotionTargetState) {}
func apply(state: MotionTransitionState) {}
/**
Starts the animations with an appearing boolean flag.
......
......@@ -48,7 +48,7 @@ internal class MotionCoreAnimationViewContext: MotionAnimatorViewContext {
overlayLayer = nil
}
override class func canAnimate(view: UIView, state: MotionTargetState, isAppearing: Bool) -> Bool {
override class func canAnimate(view: UIView, state: MotionTransitionState, isAppearing: Bool) -> Bool {
return nil != state.position ||
nil != state.size ||
nil != state.transform ||
......@@ -67,7 +67,7 @@ internal class MotionCoreAnimationViewContext: MotionAnimatorViewContext {
state.forceAnimate
}
override func apply(state: MotionTargetState) {
override func apply(state: MotionTransitionState) {
let ts = viewState(targetState: state)
for (key, targetValue) in ts {
......@@ -319,10 +319,10 @@ extension MotionCoreAnimationViewContext {
/**
Constructs a map of key paths to animation state values.
- Parameter targetState state: A MotionTargetState.
- Parameter targetState state: A MotionTransitionState.
- Returns: A map of key paths to animation values.
*/
fileprivate func viewState(targetState ts: MotionTargetState) -> [String: Any?] {
fileprivate func viewState(targetState ts: MotionTransitionState) -> [String: Any?] {
var ts = ts
var values = [String: Any?]()
......
......@@ -145,10 +145,10 @@ extension MotionDefaultAnimator {
/**
Applies the given state to the given view.
- Parameter state: A MotionTargetState.
- Parameter state: A MotionTransitionState.
- Parameter to view: A UIView.
*/
func apply(state: MotionTargetState, to view: UIView) {
func apply(state: MotionTransitionState, to view: UIView) {
guard let v = viewToContexts[view] else {
return
}
......
......@@ -33,7 +33,7 @@ internal class MotionViewPropertyViewContext: MotionAnimatorViewContext {
/// A reference to the UIViewPropertyAnimator.
fileprivate var viewPropertyAnimator: UIViewPropertyAnimator?
override class func canAnimate(view: UIView, state: MotionTargetState, isAppearing: Bool) -> Bool {
override class func canAnimate(view: UIView, state: MotionTransitionState, isAppearing: Bool) -> Bool {
return view is UIVisualEffectView && nil != state.opacity
}
......
......@@ -42,7 +42,7 @@ public class MotionContext {
internal var viewToAlphas = [UIView: CGFloat]()
/// A reference of view to transition target state.
internal var viewToTargetState = [UIView: MotionTargetState]()
internal var viewToTargetState = [UIView: MotionTransitionState]()
/// A reference of the superview to the subviews snapshots.
internal var superviewToNoSnapshotSubviewMap = [UIView: [(Int, UIView)]]()
......@@ -96,7 +96,7 @@ internal extension MotionContext {
}
if let i = v.motionTransitions {
viewToTargetState[v] = MotionTargetState(transitions: i)
viewToTargetState[v] = MotionTransitionState(transitions: i)
}
}
}
......@@ -106,11 +106,11 @@ internal extension MotionContext {
public extension MotionContext {
/**
A subscript that takes a given view and retrieves a
MotionTargetState if one exists.
MotionTransitionState if one exists.
- Parameter view: A UIView.
- Returns: An optional MotionTargetState.
- Returns: An optional MotionTransitionState.
*/
subscript(view: UIView) -> MotionTargetState? {
subscript(view: UIView) -> MotionTransitionState? {
get {
return viewToTargetState[view]
}
......@@ -207,7 +207,7 @@ public extension MotionContext {
case .layerRender:
snapshot = view.slowSnapshotView()
case .noSnapshot:
case .useOriginal:
if nil == superviewToNoSnapshotSubviewMap[view.superview!] {
superviewToNoSnapshotSubviewMap[view.superview!] = []
}
......@@ -268,7 +268,7 @@ public extension MotionContext {
view.layer.cornerRadius = oldCornerRadius
view.alpha = oldAlpha
if .noSnapshot != snapshotType {
if .useOriginal != snapshotType {
snapshot.layer.allowsGroupOpacity = false
if !(view is UINavigationBar), let contentView = snapshot.subviews.get(0) {
......@@ -362,7 +362,7 @@ internal extension MotionContext {
- Parameter view: A UIView.
*/
func hide(view: UIView) {
guard nil == viewToAlphas[view], .noSnapshot != self[view]?.snapshotType else {
guard nil == viewToAlphas[view], .useOriginal != self[view]?.snapshotType else {
return
}
......
......@@ -132,15 +132,11 @@ public extension MotionController {
- Parameter observer: A MotionTransitionObserver.
*/
func addTransitionObserver(observer: MotionTransitionObserver) {
defer {
transitionObservers?.append(observer)
if nil == transitionObservers {
transitionObservers = []
}
guard nil == transitionObservers else {
return
}
transitionObservers = []
transitionObservers?.append(observer)
}
}
......@@ -296,7 +292,7 @@ public extension MotionController {
return
}
let s = MotionTargetState(transitions: transitions)
let s = MotionTransitionState(transitions: transitions)
let v = context.transitionPairedView(for: view) ?? view
for a in animators {
......
/*
* The MIT License (MIT)
*
* Copyright (C) 2017, Daniel Dahan and CosmicMind, Inc. <http://cosmicmind.com>.
* All rights reserved.
*
* Original Inspiration & Author
* Copyright (c) 2016 Luke Zhao <me@lkzhao.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
import UIKit
public enum MotionCoordinateSpace {
case global
case local
case sameParent
}
......@@ -127,7 +127,7 @@ open class MotionPlugin: NSObject, MotionPreprocessor, MotionAnimator {
- state: the target state to override
- view: the view to override
*/
open func apply(state: MotionTargetState, to view: UIView) {}
open func apply(state: MotionTransitionState, to view: UIView) {}
}
// methods for enable/disable the current plugin
......
/*
* The MIT License (MIT)
*
* Copyright (C) 2017, Daniel Dahan and CosmicMind, Inc. <http://cosmicmind.com>.
* All rights reserved.
*
* Original Inspiration & Author
* Copyright (c) 2016 Luke Zhao <me@lkzhao.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
import UIKit
public enum MotionSnapshotType {
/**
This setting will optimize for different types of views.
For custom views or views with masking, .optimizedDefault might
create snapshots that appear differently than the actual view.
In that case, use .normal or .slowRender to disable the optimization.
*/
case optimized
/// snapshotView(afterScreenUpdates:)
case normal
/// layer.render(in: currentContext)
case layerRender
/**
This setting will not create a snapshot. It will animate the view directly.
This will mess up the view hierarchy, therefore, view controllers have to rebuild
their view structure after the transition finishes.
*/
case useOriginal
}
......@@ -109,8 +109,8 @@ extension MotionTransition: MotionStringConvertible {
return .useGlobalCoordinateSpace
case "useSameParentCoordinateSpace":
return .useSameParentCoordinateSpace
case "ignoreSubviewModifiers":
return .ignoreSubviewModifiers(recursive:parameters.getBool(0) ?? false)
case "ignoreSubviewTransitions":
return .ignoreSubviewTransitions(recursive:parameters.getBool(0) ?? false)
case "zPosition":
if let zPosition = parameters.getCGFloat(0) {
return .zPosition(zPosition)
......
......@@ -29,14 +29,14 @@
import UIKit
public final class MotionTransition {
/// A reference to the callback that applies the MotionTargetState.
internal let apply: (inout MotionTargetState) -> Void
/// A reference to the callback that applies the MotionTransitionState.
internal let apply: (inout MotionTransitionState) -> Void
/**
An initializer that accepts a given callback.
- Parameter applyFunction: A given callback.
*/
public init(applyFunction: @escaping (inout MotionTargetState) -> Void) {
public init(applyFunction: @escaping (inout MotionTransitionState) -> Void) {
apply = applyFunction
}
}
......@@ -458,7 +458,7 @@ extension MotionTransition {
public static func beginWith(transitions: [MotionTransition]) -> MotionTransition {
return MotionTransition { targetState in
if targetState.beginState == nil {
targetState.beginState = MotionTargetState.MotionTargetStateWrapper(state: [])
targetState.beginState = MotionTransitionStateWrapper(state: [])
}
targetState.beginState!.state.append(contentsOf: transitions)
}
......@@ -504,16 +504,16 @@ extension MotionTransition {
/**
ignore all motionTransitions attributes for a view's direct subviews.
*/
public static var ignoreSubviewModifiers: MotionTransition = .ignoreSubviewModifiers()
public static var ignoreSubviewTransitions: MotionTransition = .ignoreSubviewTransitions()
/**
ignore all motionTransitions attributes for a view's subviews.
- Parameters:
- recursive: if false, will only ignore direct subviews' transitions. default false.
*/
public static func ignoreSubviewModifiers(recursive: Bool = false) -> MotionTransition {
public static func ignoreSubviewTransitions(recursive: Bool = false) -> MotionTransition {
return MotionTransition { targetState in
targetState.ignoreSubviewModifiers = recursive
targetState.ignoreSubviewTransitions = recursive
}
}
......@@ -550,7 +550,7 @@ extension MotionTransition {
its view structure after the transition finishes.
*/
public static var useNoSnapshot: MotionTransition = MotionTransition { targetState in
targetState.snapshotType = .noSnapshot
targetState.snapshotType = .useOriginal
}
/**
......
......@@ -28,115 +28,181 @@
import UIKit
public enum MotionSnapshotType {
/// Will optimize for different type of views
/// For custom views or views with masking, .optimizedDefault might create snapshots
/// that appear differently than the actual view.
/// In that case, use .normal or .slowRender to disable the optimization
case optimized
/// snapshotView(afterScreenUpdates:)
case normal
/// layer.render(in: currentContext)
case layerRender
/// will not create snapshot. animate the view directly.
/// This will mess up the view hierarchy, therefore, view controllers have to rebuild
/// its view structure after the transition finishes
case noSnapshot
}
public enum MotionCoordinateSpace {
case global
case local
case sameParent
internal class MotionTransitionStateWrapper {
/// A reference to a MotionTransitionState.
internal var state: MotionTransitionState
/**
An initializer that accepts a given MotionTransitionState.
- Parameter state: A MotionTransitionState.
*/
internal init(state: MotionTransitionState) {
self.state = state
}
}
public struct MotionTargetState {
class MotionTargetStateWrapper {
var state: MotionTargetState
init(state: MotionTargetState) {
self.state = state
public struct MotionTransitionState {
/// The initial state that the transition will start at.
internal var beginState: MotionTransitionStateWrapper?
/// The start state if there is a match in the desition view controller.
public var beginStateIfMatched: [MotionTransition]?
/// A reference to the position.
public var position: CGPoint?
/// A reference to the size.
public var size: CGSize?
/// A reference to the transform.
public var transform: CATransform3D?
/// A reference to the opacity.
public var opacity: Float?
/// A reference to the cornerRadius.
public var cornerRadius: CGFloat?
/// A reference to the backgroundColor.
public var backgroundColor: CGColor?
/// A reference to the zPosition.
public var zPosition: CGFloat?
/// A reference to the contentsRect.
public var contentsRect: CGRect?
/// A reference to the contentsScale.
public var contentsScale: CGFloat?
/// A reference to the borderWidth.
public var borderWidth: CGFloat?
/// A reference to the borderColor.
public var borderColor: CGColor?
/// A reference to the shadowColor.
public var shadowColor: CGColor?
/// A reference to the shadowOpacity.
public var shadowOpacity: Float?
/// A reference to the shadowOffset.
public var shadowOffset: CGSize?
/// A reference to the shadowRadius.
public var shadowRadius: CGFloat?
/// A reference to the shadowPath.
public var shadowPath: CGPath?
/// A boolean for the masksToBounds state.
public var masksToBounds: Bool?
/// A boolean indicating whether to display a shadow or not.
public var displayShadow = true
/// A reference to the overlay settings.
public var overlay: (color: CGColor, opacity: CGFloat)?
/// A reference to the spring animation settings.
public var spring: (CGFloat, CGFloat)?
/// A time delay on starting the animation.
public var delay: TimeInterval = 0
/// The duration of the animation.
public var duration: TimeInterval?
/// The timing function value of the animation.
public var timingFunction: CAMediaTimingFunction?
/// The arc curve value.
public var arc: CGFloat?
/// The identifier value to match source and destination views.
public var motionIdentifier: String?
/// The cascading animation settings.
public var cascade: (TimeInterval, CascadeDirection, Bool)?
/**
A boolean indicating whether to ignore the subview transition
animations or not.
*/
public var ignoreSubviewTransitions: Bool?
/// The coordinate space to transition views within.
public var coordinateSpace: MotionCoordinateSpace?
/// Change the size of a view based on a scale factor.
public var useScaleBasedSizeChange: Bool?
/// The type of snapshot to use.
public var snapshotType: MotionSnapshotType?
/// Do not fade the view when transitioning.
public var nonFade = false
/// Force an animation.
public var forceAnimate = false
/// Custom target states.
public var custom: [String: Any]?
/**
An initializer that accepts an Array of MotionTransitions.
- Parameter transitions: An Array of MotionTransitions.
*/
init(transitions: [MotionTransition]) {
append(contentsOf: transitions)
}
}
internal var beginState: MotionTargetStateWrapper?
public var beginStateIfMatched: [MotionTransition]?
public var position: CGPoint?
public var size: CGSize?
public var transform: CATransform3D?
public var opacity: Float?
public var cornerRadius: CGFloat?
public var backgroundColor: CGColor?
public var zPosition: CGFloat?
public var contentsRect: CGRect?
public var contentsScale: CGFloat?
public var borderWidth: CGFloat?
public var borderColor: CGColor?
public var shadowColor: CGColor?
public var shadowOpacity: Float?
public var shadowOffset: CGSize?
public var shadowRadius: CGFloat?
public var shadowPath: CGPath?
public var masksToBounds: Bool?
public var displayShadow: Bool = true
public var overlay: (color: CGColor, opacity: CGFloat)?
public var spring: (CGFloat, CGFloat)?
public var delay: TimeInterval = 0
public var duration: TimeInterval?
public var timingFunction: CAMediaTimingFunction?
public var arc: CGFloat?
public var motionIdentifier: String?
public var cascade: (TimeInterval, CascadeDirection, Bool)?
public var ignoreSubviewModifiers: Bool?
public var coordinateSpace: MotionCoordinateSpace?
public var useScaleBasedSizeChange: Bool?
public var snapshotType: MotionSnapshotType?
public var nonFade: Bool = false
public var forceAnimate: Bool = false
public var custom: [String:Any]?
init(transitions: [MotionTransition]) {
append(contentsOf: transitions)
}
public mutating func append(_ transition: MotionTransition) {
transition.apply(&self)
}
}
public mutating func append(contentsOf transitions: [MotionTransition]) {
for modifier in transitions {
modifier.apply(&self)
extension MotionTransitionState {
/**
Adds a MotionTransition to the current state.
- Parameter _ transition: A MotionTransition.
*/
public mutating func append(_ transition: MotionTransition) {
transition.apply(&self)
}
}
/**
- Returns: custom item for a specific key
*/
public subscript(key: String) -> Any? {
get {
return custom?[key]
/**
Adds an Array of MotionTransitions to the current state.
- Parameter contentsOf transitions: An Array of MotionTransitions.
*/
public mutating func append(contentsOf transitions: [MotionTransition]) {
for v in transitions {
v.apply(&self)
}
}
set {
if custom == nil {
custom = [:]
}
custom![key] = newValue
/**
A subscript that returns a custom value for a specified key.
- Parameter key: A String.
- Returns: An optional Any value.
*/
public subscript(key: String) -> Any? {
get {
return custom?[key]
}
set(value) {
if nil == custom {
custom = [:]
}
custom![key] = value
}
}
}
}
extension MotionTargetState: ExpressibleByArrayLiteral {
public init(arrayLiteral elements: MotionTransition...) {
append(contentsOf: elements)
}
extension MotionTransitionState: ExpressibleByArrayLiteral {
/**
An initializer implementing the ExpressibleByArrayLiteral protocol.
- Parameter arrayLiteral elements: A list of MotionTransitions.
*/
public init(arrayLiteral elements: MotionTransition...) {
append(contentsOf: elements)
}
}
......@@ -39,7 +39,7 @@ class IgnoreSubviewModifiersPreprocessor: MotionPreprocessor {
func process(views: [UIView]) {
for view in views {
guard let recursive = context[view]?.ignoreSubviewModifiers else { continue }
guard let recursive = context[view]?.ignoreSubviewTransitions else { continue }
var parentView = view
if view is UITableView, let wrapperView = view.subviews.get(0) {
parentView = wrapperView
......
......@@ -41,8 +41,8 @@ class MatchPreprocessor: MotionPreprocessor {
for tv in toViews {
guard let id = tv.motionIdentifier, let fv = context.sourceView(for: id) else { continue }
var tvState = context[tv] ?? MotionTargetState()
var fvState = context[fv] ?? MotionTargetState()
var tvState = context[tv] ?? MotionTransitionState()
var fvState = context[fv] ?? MotionTransitionState()
if let beginStateIfMatched = tvState.beginStateIfMatched {
tvState.append(.beginWith(transitions: beginStateIfMatched))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment