Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import UIKit
- @objc protocol StatusBarAnimatable where Self: UIViewController {
- var isAnimatableHiding: Bool { get }
- var statusBarAnimatableAnimationDuration: TimeInterval { get }
- var statusBarAnimatableUpdateAnimation: UIStatusBarAnimation { get }
- @objc optional var isAnimatableAfterInteractivity: Bool { get }
- }
- private let swizzling: (AnyClass, Selector, Selector) -> Void = { forClass, originalSelector, swizzledSelector in
- let originalMethod = class_getInstanceMethod(forClass, originalSelector)!
- let swizzledMethod = class_getInstanceMethod(forClass, swizzledSelector)!
- method_exchangeImplementations(originalMethod, swizzledMethod)
- }
- extension UIViewController {
- static func doSwizzle() {
- do {
- let originalSelector = #selector(viewWillAppear(_:))
- let swizzledSelector = #selector(swizzled_viewWillAppear(_:))
- swizzling(UIViewController.self, originalSelector, swizzledSelector)
- }
- do {
- let originalSelector = #selector(viewDidDisappear(_:))
- let swizzledSelector = #selector(swizzled_viewDidDisappear(_:))
- swizzling(UIViewController.self, originalSelector, swizzledSelector)
- }
- do {
- let originalSelector = #selector(getter: preferredStatusBarUpdateAnimation)
- let swizzledSelector = #selector(getter: swizzled_preferredStatusBarUpdateAnimation)
- swizzling(UIViewController.self, originalSelector, swizzledSelector)
- }
- }
- @objc func swizzled_viewWillAppear(_ animated: Bool) {
- self.swizzled_viewWillAppear(animated)
- if let avc = self as? StatusBarAnimatable {
- avc.performViewWillAppear()
- }
- }
- @objc func swizzled_viewDidDisappear(_ animated: Bool) {
- self.swizzled_viewDidDisappear(animated)
- if let avc = self as? StatusBarAnimatable {
- avc.performViewDidDisappear()
- }
- }
- // swiftlint:disable:next identifier_name
- @objc var swizzled_preferredStatusBarUpdateAnimation: UIStatusBarAnimation {
- if let avc = self as? StatusBarAnimatable {
- return avc.statusBarAnimatableUpdateAnimation
- } else {
- return self.swizzled_preferredStatusBarUpdateAnimation
- }
- }
- }
- private var key: Void?
- extension StatusBarAnimatable {
- var shouldHideStatusBar: Bool {
- get {
- return (objc_getAssociatedObject(self, &key) as? Bool) ?? UIApplication.shared.isStatusBarHidden
- }
- set {
- objc_setAssociatedObject(self, &key, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
- }
- }
- fileprivate func performViewWillAppear() {
- guard let coordinator = transitionCoordinator else { return }
- let onlyAfterNonInteractive = isAnimatableAfterInteractivity ?? true
- if onlyAfterNonInteractive && coordinator.initiallyInteractive {
- coordinator.notifyWhenInteractionChanges { [unowned self] (ctx) in
- if ctx.isCancelled { return }
- self.shouldHideStatusBar = self.isAnimatableHiding
- UIView.animate(withDuration: self.statusBarAnimatableAnimationDuration) {
- self.setNeedsStatusBarAppearanceUpdate()
- }
- }
- } else {
- coordinator.animate(alongsideTransition: { [unowned self] (_) in
- self.shouldHideStatusBar = self.isAnimatableHiding
- UIView.animate(withDuration: self.statusBarAnimatableAnimationDuration) {
- self.setNeedsStatusBarAppearanceUpdate()
- }
- })
- }
- }
- fileprivate func performViewDidDisappear() {
- self.shouldHideStatusBar = UIApplication.shared.isStatusBarHidden
- }
- }
- import UIKit
- struct StatusBarAnimatableConfig {
- let isPrefersHidden: Bool
- let animation: UIStatusBarAnimation
- let animationDuration: TimeInterval?
- let isAnimatableAfterInteractivity: Bool
- }
- extension StatusBarAnimatableConfig {
- init(isPrefersHidden: Bool, animation: UIStatusBarAnimation) {
- self.init(isPrefersHidden: isPrefersHidden,
- animation: animation,
- animationDuration: nil,
- isAnimatableAfterInteractivity: true)
- }
- }
- class StatusBarAnimatableViewController: UIViewController {
- private var shouldCurrentlyHideStatusBar = false
- override func viewWillAppear(_ animated: Bool) {
- super.viewWillAppear(animated)
- guard let coordinator = transitionCoordinator else { return }
- let config = statusBarAnimatableConfig
- let onlyAfterNonInteractive = config.isAnimatableAfterInteractivity
- if onlyAfterNonInteractive && coordinator.initiallyInteractive {
- coordinator.notifyWhenInteractionChanges { ctx in
- guard !ctx.isCancelled else { return }
- self.shouldCurrentlyHideStatusBar = config.isPrefersHidden
- UIView.animate(withDuration: config.animationDuration ?? ctx.transitionDuration) {
- self.setNeedsStatusBarAppearanceUpdate()
- }
- }
- } else {
- coordinator.animate(alongsideTransition: { ctx in
- self.shouldCurrentlyHideStatusBar = config.isPrefersHidden
- UIView.animate(withDuration: config.animationDuration ?? ctx.transitionDuration) {
- self.setNeedsStatusBarAppearanceUpdate()
- }
- })
- }
- }
- override func viewDidDisappear(_ animated: Bool) {
- super.viewDidDisappear(animated)
- shouldCurrentlyHideStatusBar = UIApplication.shared.isStatusBarHidden
- }
- final override var prefersStatusBarHidden: Bool {
- return shouldCurrentlyHideStatusBar
- }
- final override var preferredStatusBarUpdateAnimation: UIStatusBarAnimation {
- return statusBarAnimatableConfig.animation
- }
- open var statusBarAnimatableConfig: StatusBarAnimatableConfig {
- return StatusBarAnimatableConfig(isPrefersHidden: false,
- animation: .none)
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement