joelarcos
2/15/2019 - 11:00 PM

UIView+ActivityIndicator.swift

//
//  UIViewController+ActivityIndicator.swift
//  RTA
//
//  Created by Joel Arcos on 3/5/19.
//  Copyright © 2019 Albert Gedeon. All rights reserved.
//

import UIKit

var overallView: UIView = UIView()
var activityIndicatorOverlay: UIView = UIView()
var activityIndicator: UIActivityIndicatorView = UIActivityIndicatorView()
var totalAdjustment: CGFloat?

//  =================================================================================================
//  API
//  =================================================================================================
extension UIViewController {
    func showActivityIndicatorOverlay() {
        setupOverlay()
        setupActivityIndicatorOverlay()
        setupActivityIndicator()
        stackViews()
        activityIndicator.startAnimating()
    }
    
    // remove activity indicator from this view
    func hideActivityIndicatorOverlay() {
        activityIndicator.stopAnimating()
        overallView.removeFromSuperview()
    }
}

//  =================================================================================================
//  Internal Methods
//  ================================================================================================
extension UIViewController {
    struct Colors {
        static let white = UIColorFromHex(rgbValue: 0xffffff, alpha: 0.3)
        static let dark = UIColorFromHex(rgbValue: 0x444444, alpha: 0.7)
    }
    
    private func setupOverlay() {
        overallView.frame = self.view.frame
        let navBarHeight = makeHeightAdjustmentForNavBar()
        let safeAreaHeight = makeHeightAdjustmentForSafeAreaPadding()
        totalAdjustment = navBarHeight + safeAreaHeight
        overallView.center = CGPoint(x: self.view.center.x, y: self.view.center.y - (totalAdjustment ?? 0))
        overallView.backgroundColor = Colors.dark
    }
    
    private func makeHeightAdjustmentForNavBar() -> CGFloat {
        var frameHeight: CGFloat = 0.0
        if let rootVC = UIApplication.shared.keyWindow!.rootViewController {
            frameHeight = rootVC.view.frame.height
            if rootVC is UINavigationController {
                let navController = rootVC as! UINavigationController
                frameHeight = navController.navigationBar.frame.height
            }
        }
        return frameHeight
    }
    
    private func makeHeightAdjustmentForSafeAreaPadding() -> CGFloat {
        var frameHeight: CGFloat = 0.0
        let topPadding = UIApplication.shared.keyWindow!.safeAreaInsets.top
        frameHeight = frameHeight + topPadding
        return frameHeight
    }
    
    private func setupActivityIndicatorOverlay() {
        activityIndicatorOverlay.frame = CGRect.init(x: 0, y: 0, width: 80, height: 80)
        activityIndicatorOverlay.center = CGPoint(x: self.view.center.x, y: self.view.center.y - (totalAdjustment ?? 0))
        activityIndicatorOverlay.backgroundColor = Colors.white
        activityIndicatorOverlay.clipsToBounds = true
        activityIndicatorOverlay.layer.cornerRadius = 10
    }
    
    private func setupActivityIndicator() {
        activityIndicator.frame = CGRect.init(x: 0.0, y: 0.0, width: 40.0, height: 40.0)
        activityIndicator.style = UIActivityIndicatorView.Style.whiteLarge
        activityIndicator.center = CGPoint.init(x: activityIndicatorOverlay.frame.size.width / 2, y: activityIndicatorOverlay.frame.size.height / 2)
    }
    
    private func stackViews() {
        activityIndicatorOverlay.addSubview(activityIndicator)
        overallView.addSubview(activityIndicatorOverlay)
        self.view.addSubview(overallView)
    }
    
    //Define UIColor from hex value
    private static func UIColorFromHex(rgbValue:UInt32, alpha:Double=1.0)->UIColor {
        let red = CGFloat((rgbValue & 0xFF0000) >> 16)/256.0
        let green = CGFloat((rgbValue & 0xFF00) >> 8)/256.0
        let blue = CGFloat(rgbValue & 0xFF)/256.0
        return UIColor(red:red, green:green, blue:blue, alpha:CGFloat(alpha))
    }
    
    
}