diff --git a/Sources/Classes/Full View/DefaultFullViewAnimations.swift b/Sources/Classes/Full View/DefaultFullViewAnimations.swift index bf73516..908d945 100644 --- a/Sources/Classes/Full View/DefaultFullViewAnimations.swift +++ b/Sources/Classes/Full View/DefaultFullViewAnimations.swift @@ -90,9 +90,11 @@ public extension Spruce { /// - sortFunction: the `sortFunction` to be used when setting the offsets for each subviews animation /// - prepare: a `bool` as to whether we should run `prepare` on your view for you. If set to `true`, then we will run `prepare` right before the animation using the stock animations that you provided. If `false`, then `prepare` will not run. (default is `true`) /// - completion: a closure that is called upon the final animation completing. A `Bool` is passed into the closure letting you know if the animation has completed. **Note:** If you stop animations on the whole animating view, then `false` will be passed into the completion closure. However, if the final animation is allowed to proceed then `true` will be the value passed into the completion closure. - public func animate(_ animations: [StockAnimation], duration: TimeInterval = 0.3, animationType: Animation, sortFunction: SortFunction, prepare: Bool = true, completion: CompletionHandler? = nil) { + public func animate(_ animations: [StockAnimation], duration: TimeInterval = 0.3, animationType: Animation, sortFunction: SortFunction, options: [AnimationOption] = [], completion: CompletionHandler? = nil) { - if prepare { + let animationObject = AnimationOptionObject(options: options) + + if animationObject.shouldPrepare { self.prepare(with: animations) } diff --git a/Sources/Classes/Full View/FullViewAnimation.swift b/Sources/Classes/Full View/FullViewAnimation.swift index c69166d..b343464 100644 --- a/Sources/Classes/Full View/FullViewAnimation.swift +++ b/Sources/Classes/Full View/FullViewAnimation.swift @@ -49,20 +49,22 @@ public extension Spruce { /// - sortFunction: the `SortFunction` used to determine the animation offsets for each subview /// - prepare: a closure that will be called with each subview of `this` parent view /// - animation: a `Animation` that will be used to animate each subview - /// - exclude: an array of views that the animation should skip over + /// - options: an array of AnimationOptions that should be applied to the Spruce animation /// - recursiveDepth: an int describing how deep into the view hiearchy the subview search should go, defaults to 0 /// - completion: a closure that is called upon the final animation completing. A `Bool` is passed into the closure letting you know if the animation has completed. **Note:** If you stop animations on the whole animating view, then `false` will be passed into the completion closure. However, if the final animation is allowed to proceed then `true` will be the value passed into the completion closure. - public func animate(withSortFunction sortFunction: SortFunction, prepare: PrepareHandler? = nil, animation: Animation, exclude: [UIView]? = nil, recursiveDepth: Int = 0, completion: CompletionHandler? = nil) { - var timedViews = sortFunction.timeOffsets(view: self.view, recursiveDepth: recursiveDepth) + public func animate(withSortFunction sortFunction: SortFunction, prepare: PrepareHandler? = nil, animation: Animation, options: [AnimationOption] = [], completion: CompletionHandler? = nil) { + + let optionsObject = AnimationOptionObject(options: options) + + var timedViews = sortFunction.timeOffsets(view: self.view, recursiveDepth: optionsObject.recursiveDepth) timedViews = timedViews.sorted { (left, right) -> Bool in return left.timeOffset < right.timeOffset } for (index, timedView) in timedViews.enumerated() { - if let exclude = exclude, exclude.reduce(false, { $0 || $1 == timedView.spruceView.view }) { + if optionsObject.excludedViews.reduce(false, { $0 || $1 == timedView.spruceView.view }) { continue } - guard let animatedView = timedView.spruceView.view else { continue } diff --git a/Sources/Classes/Full View/ViewController.swift b/Sources/Classes/Full View/ViewController.swift index c97b7dc..e7c4c72 100644 --- a/Sources/Classes/Full View/ViewController.swift +++ b/Sources/Classes/Full View/ViewController.swift @@ -67,6 +67,6 @@ open class ViewController: UIViewController { override open func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) - animationView?.spruce.animate(animations, duration: duration, animationType: animationType, sortFunction: sortFunction, prepare: false) + animationView?.spruce.animate(animations, duration: duration, animationType: animationType, sortFunction: sortFunction) } } diff --git a/Sources/Classes/SpruceAnimationOptions.swift b/Sources/Classes/SpruceAnimationOptions.swift new file mode 100644 index 0000000..a28eb75 --- /dev/null +++ b/Sources/Classes/SpruceAnimationOptions.swift @@ -0,0 +1,59 @@ +// +// Spruce.swift +// Spruce +// +// Copyright (c) 2017 WillowTree, Inc. + +// 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 Foundation + +/// Defines the options for handling a Spruce animation +/// +/// - excludeViews: the views that should be excluded in the Spruce animation +/// - prepare: If set, then Spruce will handle the preparation of the animation for you. Meaning a reverse +/// transform will be applied so that the animation runs smoothly +/// - recursiveDepth: how far into the view hierarchy the animation should run +public enum AnimationOption { + case excludedViews([UIView]) + case prepare + case recursiveDepth(Int) +} + + +/// An internal object that is used to interpret the AnimationOption's +struct AnimationOptionObject { + var excludedViews: [UIView] = [] + var shouldPrepare: Bool = false + var recursiveDepth: Int = 0 + + init(options: [AnimationOption]) { + for option in options { + switch option { + case .excludedViews(let views): + self.excludedViews = views + case .prepare: + self.shouldPrepare = true + case .recursiveDepth(let depth): + self.recursiveDepth = depth + } + } + } +} diff --git a/Spruce/Spruce.xcodeproj/project.pbxproj b/Spruce/Spruce.xcodeproj/project.pbxproj index 69030ef..bbdc10b 100644 --- a/Spruce/Spruce.xcodeproj/project.pbxproj +++ b/Spruce/Spruce.xcodeproj/project.pbxproj @@ -10,6 +10,7 @@ 3208F65B1E0B144600847FF0 /* ContinuousSortFunction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3208F65A1E0B144600847FF0 /* ContinuousSortFunction.swift */; }; 3208F65D1E0B145800847FF0 /* ContinuousWeightedSortFunction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3208F65C1E0B145800847FF0 /* ContinuousWeightedSortFunction.swift */; }; 32DC68471E09BA5B00DF8286 /* InlineSortFunction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32DC68461E09BA5B00DF8286 /* InlineSortFunction.swift */; }; + 629CE9F6201FACC700C045D2 /* SpruceAnimationOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 629CE9F5201FACC700C045D2 /* SpruceAnimationOptions.swift */; }; DB20E5771E4BADA9004C5A96 /* RadialSortFunctionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB20E5761E4BADA9004C5A96 /* RadialSortFunctionTests.swift */; }; DB288BAC1E671B810038B13E /* DirectionSortFunction.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB288BA81E671B810038B13E /* DirectionSortFunction.swift */; }; DB288BAE1E671B810038B13E /* DistanceSortFunction.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB288BA91E671B810038B13E /* DistanceSortFunction.swift */; }; @@ -62,6 +63,7 @@ 3208F65A1E0B144600847FF0 /* ContinuousSortFunction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContinuousSortFunction.swift; sourceTree = ""; }; 3208F65C1E0B145800847FF0 /* ContinuousWeightedSortFunction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContinuousWeightedSortFunction.swift; sourceTree = ""; }; 32DC68461E09BA5B00DF8286 /* InlineSortFunction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InlineSortFunction.swift; sourceTree = ""; }; + 629CE9F5201FACC700C045D2 /* SpruceAnimationOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpruceAnimationOptions.swift; sourceTree = ""; }; DB20E5761E4BADA9004C5A96 /* RadialSortFunctionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RadialSortFunctionTests.swift; sourceTree = ""; }; DB288BA81E671B810038B13E /* DirectionSortFunction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DirectionSortFunction.swift; sourceTree = ""; }; DB288BA91E671B810038B13E /* DistanceSortFunction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DistanceSortFunction.swift; sourceTree = ""; }; @@ -186,6 +188,7 @@ isa = PBXGroup; children = ( DB9358581E008E1E00ADC5BE /* Spruce.swift */, + 629CE9F5201FACC700C045D2 /* SpruceAnimationOptions.swift */, DBAFE66C1E70879D00006353 /* UIView+Spruce.swift */, DB93581D1E008DB600ADC5BE /* Full View */, DB93581C1E008DAD00ADC5BE /* UI Elements */, @@ -402,6 +405,7 @@ 3208F65D1E0B145800847FF0 /* ContinuousWeightedSortFunction.swift in Sources */, DB9358281E008DE100ADC5BE /* StandardAnimation.swift in Sources */, DB93582F1E008DE900ADC5BE /* FullViewAnimation.swift in Sources */, + 629CE9F6201FACC700C045D2 /* SpruceAnimationOptions.swift in Sources */, DB9358511E008E1200ADC5BE /* PointOperations.swift in Sources */, DB93582D1E008DE900ADC5BE /* DefaultFullViewAnimations.swift in Sources */, DB288BB81E671F2F0038B13E /* WeightSortFunction.swift in Sources */,