Skip to content

Instantly share code, notes, and snippets.

@riccardo-lomazzi
Created October 18, 2020 09:48
Show Gist options
  • Save riccardo-lomazzi/9cce7bedf14b8b50240075480161a8bb to your computer and use it in GitHub Desktop.
Save riccardo-lomazzi/9cce7bedf14b8b50240075480161a8bb to your computer and use it in GitHub Desktop.
Swift translation (WIP) of LOActivityAlertController
//
// 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