diff --git a/TIUIElements/Sources/Helpers/DefaultAnimators/ParalaxAnimator.swift b/TIUIElements/Sources/Helpers/DefaultAnimators/ParalaxAnimator.swift index 26559108..7f66ba40 100644 --- a/TIUIElements/Sources/Helpers/DefaultAnimators/ParalaxAnimator.swift +++ b/TIUIElements/Sources/Helpers/DefaultAnimators/ParalaxAnimator.swift @@ -1,37 +1,24 @@ import UIKit final public class ParalaxAnimator: CollapsibleViewsAnimator { - public var fractionComplete: CGFloat = 0 - var isWithAlphaAnimate = true - - init(isWithAlphaAnimate: Bool = true) { - self.isWithAlphaAnimate = isWithAlphaAnimate - } - - public func setupView(holder: CollapsibleViewsHolder, container: CollapsibleViewsContainer ) { - guard let largeHeaderView = container.bottomHeaderView else { - return - } - - holder.navBar?.topItem?.titleView?.alpha = 0 - - let tableHeaderView = ParallaxTableHeaderView(wrappedView: largeHeaderView) - - holder.tableView.tableHeaderView = tableHeaderView - } - - public func animate(holder: CollapsibleViewsHolder) { - paralax(holder: holder) - if isWithAlphaAnimate { - holder.navBar?.topItem?.titleView?.alpha = fractionComplete == 1 ? 1 : 0 + public var fractionComplete: CGFloat = 0 { + didSet { + navBar?.topItem?.titleView?.alpha = fractionComplete == 1 ? 1 : 0 } } - - private func paralax(holder: CollapsibleViewsHolder) { - guard let header = holder.tableView.tableHeaderView as? ParallaxTableHeaderView else { - return + + public var currentContentOffset: CGPoint { + didSet { + tableHeaderView?.layout(for: currentContentOffset) } - - header.layout(for: holder.tableView.contentOffset) + } + + private weak var navBar: UINavigationBar? + private weak var tableHeaderView: ParallaxTableHeaderView? + + public init(tableHeaderView: ParallaxTableHeaderView, navBar: UINavigationBar? = nil, currentContentOffset: CGPoint) { // if nil - no alpha animation + self.currentContentOffset = currentContentOffset + self.tableHeaderView = tableHeaderView + self.navBar = navBar } } diff --git a/TIUIElements/Sources/Helpers/DefaultAnimators/ParalaxWithScaleAnimator.swift b/TIUIElements/Sources/Helpers/DefaultAnimators/ParalaxWithScaleAnimator.swift index 2662c3a7..825f1aad 100644 --- a/TIUIElements/Sources/Helpers/DefaultAnimators/ParalaxWithScaleAnimator.swift +++ b/TIUIElements/Sources/Helpers/DefaultAnimators/ParalaxWithScaleAnimator.swift @@ -1,8 +1,8 @@ import UIKit final public class ParalaxWithScaleAnimator: CollapsibleViewsAnimator { - private let paralaxAnimator = ParalaxAnimator(isWithAlphaAnimate: false) - private let scaleAnimator = ScaleAnimator() + private let paralaxAnimator: ParalaxAnimator + private let scaleAnimator: ScaleAnimator public var fractionComplete: CGFloat = 0 { didSet { @@ -10,14 +10,20 @@ final public class ParalaxWithScaleAnimator: CollapsibleViewsAnimator { scaleAnimator.fractionComplete = fractionComplete } } - - public func setupView(holder: CollapsibleViewsHolder, container: CollapsibleViewsContainer) { - paralaxAnimator.setupView(holder: holder, container: container) - scaleAnimator.setupView(holder: holder, container: container) + + public var currentContentOffset: CGPoint { + didSet { + paralaxAnimator.currentContentOffset = currentContentOffset + scaleAnimator.currentContentOffset = currentContentOffset + } } - - public func animate(holder: CollapsibleViewsHolder) { - paralaxAnimator.animate(holder: holder) - scaleAnimator.animate(holder: holder) + + private weak var navBar: UINavigationBar? + + public init(tableHeaderView: ParallaxTableHeaderView, navBar: UINavigationBar? = nil, currentContentOffset: CGPoint) { + self.navBar = navBar + paralaxAnimator = ParalaxAnimator(tableHeaderView: tableHeaderView, navBar: nil, currentContentOffset: currentContentOffset) + scaleAnimator = ScaleAnimator(navBar: navBar) + self.currentContentOffset = currentContentOffset } } diff --git a/TIUIElements/Sources/Helpers/DefaultAnimators/ParalaxWithTransitionAnimator .swift b/TIUIElements/Sources/Helpers/DefaultAnimators/ParalaxWithTransitionAnimator .swift index a12995ce..04aa7565 100644 --- a/TIUIElements/Sources/Helpers/DefaultAnimators/ParalaxWithTransitionAnimator .swift +++ b/TIUIElements/Sources/Helpers/DefaultAnimators/ParalaxWithTransitionAnimator .swift @@ -1,8 +1,8 @@ import UIKit final public class ParalaxWithTransitionAnimator: CollapsibleViewsAnimator { - private let paralaxAnimator = ParalaxAnimator(isWithAlphaAnimate: false) - private let transitionAnimator = TransitionAnimator() + private let paralaxAnimator: ParalaxAnimator + private let transitionAnimator: TransitionAnimator public var fractionComplete: CGFloat = 0 { didSet { @@ -10,14 +10,20 @@ final public class ParalaxWithTransitionAnimator: CollapsibleViewsAnimator { transitionAnimator.fractionComplete = fractionComplete } } - - public func setupView(holder: CollapsibleViewsHolder, container: CollapsibleViewsContainer) { - paralaxAnimator.setupView(holder: holder, container: container) - transitionAnimator.setupView(holder: holder, container: container) + + public var currentContentOffset: CGPoint { + didSet { + paralaxAnimator.currentContentOffset = currentContentOffset + transitionAnimator.currentContentOffset = currentContentOffset + } } - - public func animate(holder: CollapsibleViewsHolder) { - paralaxAnimator.animate(holder: holder) - transitionAnimator.animate(holder: holder) + + private weak var navBar: UINavigationBar? + + public init(tableHeaderView: ParallaxTableHeaderView, navBar: UINavigationBar? = nil, currentContentOffset: CGPoint) { + self.navBar = navBar + paralaxAnimator = ParalaxAnimator(tableHeaderView: tableHeaderView, navBar: nil, currentContentOffset: currentContentOffset) + transitionAnimator = TransitionAnimator(navBar: navBar) + self.currentContentOffset = currentContentOffset } } diff --git a/TIUIElements/Sources/Helpers/DefaultAnimators/ScaleAnimator.swift b/TIUIElements/Sources/Helpers/DefaultAnimators/ScaleAnimator.swift index 4f2e4727..b574d232 100644 --- a/TIUIElements/Sources/Helpers/DefaultAnimators/ScaleAnimator.swift +++ b/TIUIElements/Sources/Helpers/DefaultAnimators/ScaleAnimator.swift @@ -1,14 +1,19 @@ import UIKit final public class ScaleAnimator: CollapsibleViewsAnimator { - public var fractionComplete: CGFloat = 0 - - public func setupView(holder: CollapsibleViewsHolder, container: CollapsibleViewsContainer) { - holder.navBar?.topItem?.titleView?.alpha = 0 - holder.navBar?.topItem?.titleView?.transform = CGAffineTransform(scaleX: -0.5, y: 0.5) + public var fractionComplete: CGFloat = 0 { + didSet { + navBar?.topItem?.titleView?.scale(to: fractionComplete) + } } - - public func animate(holder: CollapsibleViewsHolder) { - holder.navBar?.topItem?.titleView?.scale(to: fractionComplete) + + public var currentContentOffset = CGPoint.zero + + private weak var navBar: UINavigationBar? + + public init(navBar: UINavigationBar? = nil) { + self.navBar = navBar + navBar?.topItem?.titleView?.alpha = 0 + navBar?.topItem?.titleView?.transform = CGAffineTransform(scaleX: -0.5, y: 0.5) } } diff --git a/TIUIElements/Sources/Helpers/DefaultAnimators/TransitionAnimator.swift b/TIUIElements/Sources/Helpers/DefaultAnimators/TransitionAnimator.swift index dcb002e4..33b631ca 100644 --- a/TIUIElements/Sources/Helpers/DefaultAnimators/TransitionAnimator.swift +++ b/TIUIElements/Sources/Helpers/DefaultAnimators/TransitionAnimator.swift @@ -1,13 +1,18 @@ import UIKit final public class TransitionAnimator: CollapsibleViewsAnimator { - public var fractionComplete: CGFloat = 0 - - public func setupView(holder: CollapsibleViewsHolder, container: CollapsibleViewsContainer) { - holder.navBar?.topItem?.titleView?.alpha = 0 + public var fractionComplete: CGFloat = 0 { + didSet { + navBar?.topItem?.titleView?.transition(to: fractionComplete) + } } - - public func animate(holder: CollapsibleViewsHolder) { - holder.navBar?.topItem?.titleView?.transition(to: fractionComplete) + + public var currentContentOffset = CGPoint.zero + + private weak var navBar: UINavigationBar? + + public init(navBar: UINavigationBar? = nil) { + navBar?.topItem?.titleView?.alpha = 0 + self.navBar = navBar } } diff --git a/TIUIElements/Sources/Helpers/Extensions/UIView+Animate.swift b/TIUIElements/Sources/Helpers/Extensions/UIView+Animate.swift index c71f4d84..a580df4e 100644 --- a/TIUIElements/Sources/Helpers/Extensions/UIView+Animate.swift +++ b/TIUIElements/Sources/Helpers/Extensions/UIView+Animate.swift @@ -1,14 +1,14 @@ import UIKit -extension UIView { - public func transition(to coefficient: CGFloat) { +public extension UIView { + func transition(to coefficient: CGFloat) { UIView.animate(withDuration: 0.2) { [weak self] in self?.alpha = coefficient self?.transform = CGAffineTransform(translationX: 0, y: -coefficient*10) } } - public func scale(to coefficient: CGFloat) { + func scale(to coefficient: CGFloat) { UIView.animate(withDuration: 0.2){ [weak self] in self?.alpha = coefficient self?.transform = CGAffineTransform(scaleX: coefficient, y: coefficient) diff --git a/TIUIElements/Sources/Helpers/Protocols/CollapsibleViewsAnimator.swift b/TIUIElements/Sources/Helpers/Protocols/CollapsibleViewsAnimator.swift index 3b083d64..fe0ddcbd 100644 --- a/TIUIElements/Sources/Helpers/Protocols/CollapsibleViewsAnimator.swift +++ b/TIUIElements/Sources/Helpers/Protocols/CollapsibleViewsAnimator.swift @@ -1,10 +1,6 @@ import UIKit -public typealias CollapsibleViewsHolder = TableViewHolder & NavigationBarHolder - public protocol CollapsibleViewsAnimator { - var fractionComplete: CGFloat { get set } // progress of animation - - func setupView(holder: CollapsibleViewsHolder, container: CollapsibleViewsContainer) - func animate(holder: CollapsibleViewsHolder) + var fractionComplete: CGFloat { get set } // progress of animation + var currentContentOffset: CGPoint { get set } // offset on content in table view/collection view or plain scroll view } diff --git a/TIUIElements/Sources/Helpers/Protocols/CollapsibleViewsContainer.swift b/TIUIElements/Sources/Helpers/Protocols/CollapsibleViewsContainer.swift index 4fca90dd..9bb97810 100644 --- a/TIUIElements/Sources/Helpers/Protocols/CollapsibleViewsContainer.swift +++ b/TIUIElements/Sources/Helpers/Protocols/CollapsibleViewsContainer.swift @@ -1,6 +1,6 @@ import UIKit -public protocol CollapsibleViewsContainer { +public protocol CollapsibleViewsContainer { var topHeaderView: UIView? { get } // titleView var bottomHeaderView: UIView? { get } // tableHeaderView diff --git a/TIUIElements/Sources/Helpers/Protocols/TransitioningHandler.swift b/TIUIElements/Sources/Helpers/Protocols/TransitioningHandler.swift index efb8d9fb..850f1fb6 100644 --- a/TIUIElements/Sources/Helpers/Protocols/TransitioningHandler.swift +++ b/TIUIElements/Sources/Helpers/Protocols/TransitioningHandler.swift @@ -1,9 +1,7 @@ import UIKit public protocol TransitioningHandler: UIScrollViewDelegate { - var animator: CollapsibleViewsAnimator? { get set } + var animator: CollapsibleViewsAnimator? { get set } - init(collapsibleViewsContainer: CollapsibleViewsContainer?, - collapsibleViewsHolder: CollapsibleViewsHolder?, - animator: CollapsibleViewsAnimator?) -} + init(collapsibleViewsContainer: CollapsibleViewsContainer) + } diff --git a/TIUIElements/Sources/Helpers/TableViewHeaderTransitioningHandler.swift b/TIUIElements/Sources/Helpers/TableViewHeaderTransitioningHandler.swift index 1ece4560..3ca66be2 100644 --- a/TIUIElements/Sources/Helpers/TableViewHeaderTransitioningHandler.swift +++ b/TIUIElements/Sources/Helpers/TableViewHeaderTransitioningHandler.swift @@ -1,97 +1,34 @@ -import Foundation import UIKit -final public class TableViewHeaderTransitioningHandler: NSObject, TransitioningHandler { - public var animator: CollapsibleViewsAnimator? - - private var collapsibleViewsContainer: CollapsibleViewsContainer? - private var collapsibleViewsHolder: CollapsibleViewsHolder? - +final class TableViewHeaderTransitioningHandler: NSObject, TransitioningHandler { + var animator: CollapsibleViewsAnimator? + private var startOffset: CGFloat = 0 private var navigationBarOffset: CGFloat = 0 private var isFirstScroll = true - - private var titleView: UIView? { - get { - collapsibleViewsHolder?.navBar?.topItem?.titleView - } - set { - collapsibleViewsHolder?.navBar?.topItem?.titleView = newValue - } + + private var container: CollapsibleViewsContainer? + + init(collapsibleViewsContainer: CollapsibleViewsContainer) { + self.container = collapsibleViewsContainer } - - private var tableHeaderView: UIView? { - get { - collapsibleViewsHolder?.tableView.tableHeaderView - } - set { - collapsibleViewsHolder?.tableView.tableHeaderView = newValue - } - } - - public init(collapsibleViewsContainer: CollapsibleViewsContainer?, - collapsibleViewsHolder: CollapsibleViewsHolder?, - animator: CollapsibleViewsAnimator?) { - self.collapsibleViewsContainer = collapsibleViewsContainer - self.collapsibleViewsHolder = collapsibleViewsHolder - self.animator = animator - super.init() - - initialUpdateHeaderView() - } - + public func scrollViewDidScroll(_ scrollView: UIScrollView) { - guard let largeHeaderView = collapsibleViewsContainer?.bottomHeaderView else { - titleView?.isHidden = false + guard let largeHeaderView = container?.bottomHeaderView else { return } - + if isFirstScroll { - startOffset = max(-(collapsibleViewsHolder?.startOffset.y ?? 0), 0) - navigationBarOffset = collapsibleViewsContainer?.fixedTopOffet ?? 0 + startOffset = max(-(scrollView.contentOffset.y), 0) + navigationBarOffset = container?.fixedTopOffet ?? 0 isFirstScroll = false } - + let offsetY = scrollView.contentOffset.y + startOffset - - var alpha = offsetY / (largeHeaderView.frame.height + navigationBarOffset) - alpha = alpha > 1 ? 1 : alpha - - guard let collapsibleViewsHolder = collapsibleViewsHolder, - var animator = animator else { - titleView?.alpha = alpha == 1 ? 1 : 0 - return - } - - animator.fractionComplete = alpha - animator.animate(holder: collapsibleViewsHolder) - } - - private func setupView() { - titleView?.alpha = animator == nil ? 0 : 1 - guard let collapsibleViewsHolder = collapsibleViewsHolder, - let collapsibleViewsContainer = collapsibleViewsContainer, - let animator = animator else { - return - } + let alpha = min(offsetY / (largeHeaderView.frame.height + navigationBarOffset), 1) - animator.setupView(holder: collapsibleViewsHolder, container: collapsibleViewsContainer) - } - - private func initialUpdateHeaderView() { - titleView = collapsibleViewsContainer?.topHeaderView - - setLargeHeader() - - setupView() - } - - private func setLargeHeader() { - guard let largeHeaderView = collapsibleViewsContainer?.bottomHeaderView else { - return - } - - tableHeaderView = largeHeaderView + animator?.fractionComplete = alpha + animator?.currentContentOffset = scrollView.contentOffset } } diff --git a/TIUIElements/Sources/Helpers/ParallaxTableHeaderView.swift b/TIUIElements/Sources/Helpers/Views/ParallaxTableHeaderView.swift similarity index 100% rename from TIUIElements/Sources/Helpers/ParallaxTableHeaderView.swift rename to TIUIElements/Sources/Helpers/Views/ParallaxTableHeaderView.swift