diff --git a/Sources/Animator/HeroAnimatorViewContext.swift b/Sources/Animator/HeroAnimatorViewContext.swift index 86b1ecc1..bac9919e 100644 --- a/Sources/Animator/HeroAnimatorViewContext.swift +++ b/Sources/Animator/HeroAnimatorViewContext.swift @@ -44,7 +44,8 @@ internal class HeroAnimatorViewContext { func apply(state: HeroTargetState) { } - func resume(timePassed: TimeInterval, reverse: Bool) { + func resume(timePassed: TimeInterval, reverse: Bool) -> TimeInterval { + return 0 } func seek(timePassed: TimeInterval) { @@ -54,7 +55,8 @@ internal class HeroAnimatorViewContext { animator = nil } - func startAnimations() { + func startAnimations() -> TimeInterval { + return 0 } required init(animator: HeroAnimator, snapshot: UIView, targetState: HeroTargetState, appearing: Bool) { diff --git a/Sources/Animator/HeroCoreAnimationViewContext.swift b/Sources/Animator/HeroCoreAnimationViewContext.swift index 6e50080a..425e145a 100644 --- a/Sources/Animator/HeroCoreAnimationViewContext.swift +++ b/Sources/Animator/HeroCoreAnimationViewContext.swift @@ -325,7 +325,7 @@ internal class HeroCoreAnimationViewContext: HeroAnimatorViewContext { } } - override func resume(timePassed: TimeInterval, reverse: Bool) { + override func resume(timePassed: TimeInterval, reverse: Bool) -> TimeInterval { for (key, (fromValue, toValue)) in state { let realToValue = !reverse ? toValue : fromValue let realFromValue = currentValue(key: key) @@ -335,21 +335,25 @@ internal class HeroCoreAnimationViewContext: HeroAnimatorViewContext { if reverse { if timePassed > targetState.delay + duration { let backDelay = timePassed - (targetState.delay + duration) - animate(beginTime: currentTime + backDelay, duration: duration) + return animate(delay: backDelay, duration: duration) } else if timePassed > targetState.delay { - animate(beginTime: currentTime, duration: duration - (timePassed - targetState.delay)) + return animate(delay: 0, duration: duration - (timePassed - targetState.delay)) + } else { + return 0 } } else { if timePassed <= targetState.delay { - animate(beginTime: currentTime + targetState.delay - timePassed, duration: duration) + return animate(delay: targetState.delay - timePassed, duration: duration) } else if timePassed <= targetState.delay + duration { let timePassedDelay = timePassed - targetState.delay - animate(beginTime: currentTime, duration: duration - timePassedDelay) + return animate(delay: 0, duration: duration - timePassedDelay) + } else { + return 0 } } } - func animate(beginTime: TimeInterval, duration: TimeInterval) { + func animate(delay: TimeInterval, duration: TimeInterval) -> TimeInterval { for (layer, key, _) in animations { layer.removeAnimation(forKey: key) } @@ -362,11 +366,11 @@ internal class HeroCoreAnimationViewContext: HeroAnimatorViewContext { animations = [] for (key, (fromValue, toValue)) in state { - let neededTime = animate(key: key, beginTime: beginTime, duration: duration, fromValue: fromValue, toValue: toValue) + let neededTime = animate(key: key, beginTime: currentTime + delay, duration: duration, fromValue: fromValue, toValue: toValue) timeUntilStop = max(timeUntilStop, neededTime) } - self.duration = timeUntilStop + beginTime - currentTime + return timeUntilStop + delay } func seek(layer: CALayer, timePassed: TimeInterval) { @@ -394,7 +398,7 @@ internal class HeroCoreAnimationViewContext: HeroAnimatorViewContext { overlayLayer = nil } - override func startAnimations() { + override func startAnimations() -> TimeInterval { if let beginStateModifiers = targetState.beginState { let beginState = HeroTargetState(modifiers: beginStateModifiers) let appeared = viewState(targetState: beginState) @@ -417,6 +421,6 @@ internal class HeroCoreAnimationViewContext: HeroAnimatorViewContext { state[key] = (fromValue, toValue) } - animate(beginTime: currentTime + targetState.delay, duration: duration) + return animate(delay: targetState.delay, duration: duration) } } diff --git a/Sources/Animator/HeroDefaultAnimator.swift b/Sources/Animator/HeroDefaultAnimator.swift index bd39e8ae..a0dd17ba 100644 --- a/Sources/Animator/HeroDefaultAnimator.swift +++ b/Sources/Animator/HeroDefaultAnimator.swift @@ -66,8 +66,8 @@ internal class HeroDefaultAnimator: HeroAn calculateOptimizedDuration(snapshot: viewContext.snapshot, targetState: viewContext.targetState) + timePassed) } - viewContext.resume(timePassed: timePassed, reverse: reverse) - duration = max(duration, viewContext.duration) + let timeUntilStopped = viewContext.resume(timePassed: timePassed, reverse: reverse) + duration = max(duration, timeUntilStopped) } return duration } @@ -105,11 +105,8 @@ internal class HeroDefaultAnimator: HeroAn if viewContext.targetState.duration == .infinity { viewContext.duration = maxDuration } - viewContext.startAnimations() - } - - for viewContext in viewContexts.values { - maxDuration = max(maxDuration, viewContext.duration) + let timeUntilStopped = viewContext.startAnimations() + maxDuration = max(maxDuration, timeUntilStopped) } return maxDuration diff --git a/Sources/Animator/HeroViewPropertyViewContext.swift b/Sources/Animator/HeroViewPropertyViewContext.swift index db2e2480..d8eacdd8 100644 --- a/Sources/Animator/HeroViewPropertyViewContext.swift +++ b/Sources/Animator/HeroViewPropertyViewContext.swift @@ -33,8 +33,8 @@ internal class HeroViewPropertyViewContext: HeroAnimatorViewContext { return view is UIVisualEffectView && state.opacity != nil } - override func resume(timePassed: TimeInterval, reverse: Bool) { - guard let visualEffectView = snapshot as? UIVisualEffectView else { return } + override func resume(timePassed: TimeInterval, reverse: Bool) -> TimeInterval { + guard let visualEffectView = snapshot as? UIVisualEffectView else { return 0 } if reverse { viewPropertyAnimator?.stopAnimation(false) viewPropertyAnimator = UIViewPropertyAnimator(duration: duration, curve: .linear) { @@ -42,6 +42,7 @@ internal class HeroViewPropertyViewContext: HeroAnimatorViewContext { } } viewPropertyAnimator.startAnimation() + return duration } override func seek(timePassed: TimeInterval) { @@ -54,8 +55,8 @@ internal class HeroViewPropertyViewContext: HeroAnimatorViewContext { viewPropertyAnimator = nil } - override func startAnimations() { - guard let visualEffectView = snapshot as? UIVisualEffectView else { return } + override func startAnimations() -> TimeInterval { + guard let visualEffectView = snapshot as? UIVisualEffectView else { return 0 } let appearedEffect = visualEffectView.effect let disappearedEffect = targetState.opacity == 0 ? nil : visualEffectView.effect startEffect = appearing ? disappearedEffect : appearedEffect @@ -65,5 +66,6 @@ internal class HeroViewPropertyViewContext: HeroAnimatorViewContext { visualEffectView.effect = self.endEffect } viewPropertyAnimator.startAnimation() + return duration } }