diff options
| author | Andrej Mihajlov <and@mullvad.net> | 2022-07-27 08:31:30 +0200 |
|---|---|---|
| committer | Andrej Mihajlov <and@mullvad.net> | 2022-07-28 11:21:51 +0200 |
| commit | a8b89ee5e9fe985120fa21b6fd0f0e4f6f344fd8 (patch) | |
| tree | 705abf792168f002f622ff812a4eca5df68fecc6 | |
| parent | 5bd9fd932d0515bf3987d1fa8a5c28ca04cfd130 (diff) | |
| download | mullvadvpn-a8b89ee5e9fe985120fa21b6fd0f0e4f6f344fd8.tar.xz mullvadvpn-a8b89ee5e9fe985120fa21b6fd0f0e4f6f344fd8.zip | |
Add custom size for spinner, integrate with scene API and sync all animations
| -rw-r--r-- | ios/MullvadVPN/SpinnerActivityIndicatorView.swift | 91 |
1 files changed, 58 insertions, 33 deletions
diff --git a/ios/MullvadVPN/SpinnerActivityIndicatorView.swift b/ios/MullvadVPN/SpinnerActivityIndicatorView.swift index 243389a3ff..4c7332ae6f 100644 --- a/ios/MullvadVPN/SpinnerActivityIndicatorView.swift +++ b/ios/MullvadVPN/SpinnerActivityIndicatorView.swift @@ -8,21 +8,23 @@ import UIKit -private let kRotationAnimationKey = "rotation" -private let kAnimationDuration = 0.6 - class SpinnerActivityIndicatorView: UIView { + private static let rotationAnimationKey = "rotation" + private static let animationDuration = 0.6 + enum Style { - case small, medium, large + case small, medium, large, custom var intrinsicSize: CGSize { switch self { case .small: - return .init(width: 16, height: 16) + return CGSize(width: 16, height: 16) case .medium: - return .init(width: 20, height: 20) + return CGSize(width: 20, height: 20) case .large: - return .init(width: 60, height: 60) + return CGSize(width: 60, height: 60) + case .custom: + return CGSize(width: UIView.noIntrinsicMetric, height: UIView.noIntrinsicMetric) } } } @@ -32,8 +34,7 @@ class SpinnerActivityIndicatorView: UIView { private(set) var isAnimating = false private(set) var style = Style.large - private var startTime = CFTimeInterval(0) - private var stopTime = CFTimeInterval(0) + private var sceneActivationObserver: Any? override var intrinsicContentSize: CGSize { return style.intrinsicSize @@ -42,28 +43,30 @@ class SpinnerActivityIndicatorView: UIView { init(style: Style) { self.style = style - super.init(frame: CGRect(origin: .zero, size: style.intrinsicSize)) + let size = style == .custom ? .zero : style.intrinsicSize + + super.init(frame: CGRect(origin: .zero, size: size)) addSubview(imageView) isHidden = true backgroundColor = UIColor.clear - - NotificationCenter.default.addObserver( - self, - selector: #selector(restartAnimationIfNeeded), - name: UIApplication.willEnterForegroundNotification, - object: nil - ) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } + deinit { + unregisterSceneActivationObserver() + } + override func didMoveToWindow() { super.didMoveToWindow() - if window != nil { + if window == nil { + unregisterSceneActivationObserver() + } else { + registerSceneActivationObserver() restartAnimationIfNeeded() } } @@ -71,7 +74,9 @@ class SpinnerActivityIndicatorView: UIView { override func layoutSubviews() { super.layoutSubviews() - imageView.frame = CGRect(origin: .zero, size: style.intrinsicSize) + let size = style == .custom ? frame.size : style.intrinsicSize + + imageView.frame = CGRect(origin: .zero, size: size) } func startAnimating() { @@ -91,37 +96,57 @@ class SpinnerActivityIndicatorView: UIView { } private func addAnimation() { - let timeOffset = stopTime - startTime + layer.add(createAnimation(), forKey: Self.rotationAnimationKey) + } - let anim = animation() - anim.timeOffset = timeOffset + private func removeAnimation() { + layer.removeAnimation(forKey: Self.rotationAnimationKey) + } - layer.add(anim, forKey: kRotationAnimationKey) + private func registerSceneActivationObserver() { + let name: NSNotification.Name + var object: Any? - startTime = layer.convertTime(CACurrentMediaTime(), from: nil) - timeOffset - } + if #available(iOS 13, *) { + name = UIScene.willEnterForegroundNotification + object = window?.windowScene + } else { + name = UIApplication.willEnterForegroundNotification + } - private func removeAnimation() { - layer.removeAnimation(forKey: kRotationAnimationKey) + unregisterSceneActivationObserver() + + sceneActivationObserver = NotificationCenter.default.addObserver( + forName: name, + object: object, + queue: .main, using: { [weak self] _ in + self?.restartAnimationIfNeeded() + }) + } - stopTime = layer.convertTime(CACurrentMediaTime(), from: nil) + private func unregisterSceneActivationObserver() { + if let sceneActivationObserver = sceneActivationObserver { + NotificationCenter.default.removeObserver(sceneActivationObserver) + self.sceneActivationObserver = nil + } } - @objc private func restartAnimationIfNeeded() { - let anim = layer.animation(forKey: kRotationAnimationKey) + private func restartAnimationIfNeeded() { + let animation = layer.animation(forKey: Self.rotationAnimationKey) - if isAnimating && anim == nil { + if isAnimating && animation == nil { removeAnimation() addAnimation() } } - private func animation() -> CABasicAnimation { + private func createAnimation() -> CABasicAnimation { let animation = CABasicAnimation(keyPath: "transform.rotation") animation.toValue = NSNumber(value: Double.pi * 2) - animation.duration = kAnimationDuration + animation.duration = Self.animationDuration animation.repeatCount = Float.infinity animation.timingFunction = CAMediaTimingFunction(name: .linear) + animation.timeOffset = layer.convertTime(CACurrentMediaTime(), from: nil) return animation } |
