Created
October 18, 2020 09:48
-
-
Save riccardo-lomazzi/9cce7bedf14b8b50240075480161a8bb to your computer and use it in GitHub Desktop.
Swift translation (WIP) of LOActivityAlertController
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// LOActivityAlertController.swift | |
// | |
// Created by riccardo on 12/10/2020 | |
// | |
// Swift Translation of LOActivityAlertController found in this SO answer: https://stackoverflow.com/a/48730050 | |
import Foundation | |
import UIKit | |
class LOActivityAlertController: UIViewController, UIViewControllerTransitioningDelegate { | |
var activityIndicatorView: UIActivityIndicatorView! | |
var titleLabel: UILabel! | |
var messageLabel: UILabel! | |
var alertTitle: String | |
var alertMessage: String | |
init(title: String, message: String) { | |
self.alertTitle = title | |
self.alertMessage = message | |
super.init(nibName: nil, bundle: nil) | |
} | |
required init?(coder: NSCoder) { | |
fatalError("Not implemented") | |
} | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
self.transitioningDelegate = self | |
self.modalPresentationStyle = .custom | |
self.titleLabel = UILabel() | |
self.messageLabel = UILabel() | |
self.titleLabel.text = self.alertTitle | |
self.messageLabel.text = self.alertMessage | |
self.activityIndicatorView = UIActivityIndicatorView(style: .medium) | |
let currentFrame = self.view.frame | |
let alertFrame = CGRect(x: 0, y: 0, width: currentFrame.width / 2.0, height: currentFrame.height / 2.0) | |
let stackView = UIStackView(frame: alertFrame) | |
stackView.backgroundColor = .gray | |
stackView.axis = .vertical | |
stackView.alignment = .center | |
stackView.distribution = .fillProportionally | |
stackView.addArrangedSubview(self.titleLabel) | |
stackView.addArrangedSubview(self.messageLabel) | |
stackView.addArrangedSubview(self.activityIndicatorView) | |
self.activityIndicatorView.startAnimating() | |
self.view.addSubview(stackView) | |
} | |
override func viewDidAppear(_ animated: Bool) { | |
} | |
func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? { | |
let presentationController = LOActivityAlertControllerPresentationController(presentedViewController: presented, presenting: presenting) | |
return presentationController | |
} | |
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? { | |
let transitioning = LOActivityAlertControllerAnimatedTransitioning(presentation: true) | |
return transitioning | |
} | |
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { | |
let transitioning = LOActivityAlertControllerAnimatedTransitioning(presentation: false) | |
return transitioning | |
} | |
} | |
class LOActivityAlertControllerPresentationController: UIPresentationController { | |
var dimmerView: UIView! | |
override init(presentedViewController: UIViewController, presenting presentingViewController: UIViewController?) { | |
self.dimmerView = UIView() | |
super.init(presentedViewController: presentedViewController, presenting: presentingViewController) | |
dimmerView.autoresizingMask = [.flexibleWidth, .flexibleHeight] | |
dimmerView.backgroundColor = UIColor.init(white: 0, alpha: 0.4) | |
guard let presentedView = self.presentedView else { return } | |
presentedView.layer.cornerRadius = 8.0 | |
let centerXMotionEffect: UIInterpolatingMotionEffect = UIInterpolatingMotionEffect(keyPath: "center.x", type: .tiltAlongHorizontalAxis) | |
centerXMotionEffect.minimumRelativeValue = -10.0 | |
centerXMotionEffect.maximumRelativeValue = 10.0 | |
let centerYMotionEffect: UIInterpolatingMotionEffect = UIInterpolatingMotionEffect(keyPath: "center.y", type: .tiltAlongVerticalAxis) | |
centerYMotionEffect.minimumRelativeValue = -10.0 | |
centerYMotionEffect.maximumRelativeValue = 10.0 | |
let group: UIMotionEffectGroup = UIMotionEffectGroup() | |
group.motionEffects = [centerXMotionEffect, centerYMotionEffect] | |
presentedView.addMotionEffect(group) | |
} | |
override var frameOfPresentedViewInContainerView: CGRect { | |
guard let containerView = self.containerView, let presentedView = self.presentedView else { return .zero } | |
let size = presentedView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize) | |
var frame = CGRect.zero | |
frame.origin = CGPoint(x: containerView.frame.midX - (size.width / 2.0), y: containerView.frame.midY - (size.height / 2.0)) | |
frame.size = size | |
return frame | |
} | |
override func presentationTransitionWillBegin() { | |
guard let containerView: UIView = self.containerView, let presentedView: UIView = self.presentedView, let dimmerView = self.dimmerView else { return } | |
let presentingViewController: UIViewController = self.presentingViewController | |
dimmerView.alpha = 0.0 | |
dimmerView.frame = containerView.bounds | |
containerView.insertSubview(dimmerView, at: 0) | |
presentedView.center = containerView.center | |
guard let transitionCoordinator = presentingViewController.transitionCoordinator else { return } | |
transitionCoordinator.animate( | |
alongsideTransition: { _ in | |
dimmerView.alpha = 1.0 | |
}, | |
completion: nil | |
) | |
} | |
override func containerViewWillLayoutSubviews() { | |
super.containerViewWillLayoutSubviews() | |
guard let containerView: UIView = self.containerView, let presentedView: UIView = self.presentedView, let dimmerView = self.dimmerView else { return } | |
dimmerView.frame = containerView.bounds | |
presentedView.frame = self.frameOfPresentedViewInContainerView | |
} | |
override func dismissalTransitionWillBegin() { | |
guard let dimmerView = self.dimmerView, let transitionCoordinator = self.presentingViewController.transitionCoordinator else { return } | |
transitionCoordinator.animate( | |
alongsideTransition: { _ in | |
dimmerView.alpha = 0.0 | |
}, | |
completion: nil | |
) | |
} | |
} | |
class LOActivityAlertControllerAnimatedTransitioning: NSObject, UIViewControllerAnimatedTransitioning { | |
var presentation: Bool | |
init(presentation: Bool) { | |
self.presentation = presentation | |
} | |
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { | |
let containerView = transitionContext.containerView | |
guard let fromView = transitionContext.view(forKey: .from), let toView = transitionContext.view(forKey: .to) else { return } | |
if self.presentation { | |
containerView.addSubview(toView) | |
toView.transform = CGAffineTransform(scaleX: 1.6, y: 1.6) | |
toView.alpha = 0.0 | |
UIView.animate( | |
withDuration: 0.2, | |
animations: { | |
toView.alpha = 1.0 | |
toView.transform = .identity | |
}, | |
completion: { finished in | |
transitionContext.completeTransition(true) | |
} | |
) | |
} else { | |
UIView.animate( | |
withDuration: 0.2, | |
animations: { | |
fromView.alpha = 0.0 | |
}, | |
completion: { finished in | |
fromView.removeFromSuperview() | |
transitionContext.completeTransition(true) | |
} | |
) | |
} | |
} | |
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { | |
return 0.2 | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment