在 iOS 中 运行 长任务时加载 "overlay"
Loading an "overlay" when running long tasks in iOS
在Swift IOS 应用程序中执行长任务时加载叠加层的示例是什么。从远程服务器加载数据的示例。
我用谷歌搜索但没有找到任何答案。
已更新:
感谢@Sebastian Dressler,这是一种简单的方法。我更新了我的代码,它 运行 很酷
public class LoadingOverlay{
var overlayView = UIView()
var activityIndicator = UIActivityIndicatorView()
class var shared: LoadingOverlay {
struct Static {
static let instance: LoadingOverlay = LoadingOverlay()
}
return Static.instance
}
public func showOverlay(view: UIView) {
overlayView.frame = CGRectMake(0, 0, 80, 80)
overlayView.center = view.center
overlayView.backgroundColor = UIColor(hex: 0x444444, alpha: 0.7)
overlayView.clipsToBounds = true
overlayView.layer.cornerRadius = 10
activityIndicator.frame = CGRectMake(0, 0, 40, 40)
activityIndicator.activityIndicatorViewStyle = .WhiteLarge
activityIndicator.center = CGPointMake(overlayView.bounds.width / 2, overlayView.bounds.height / 2)
overlayView.addSubview(activityIndicator)
view.addSubview(overlayView)
activityIndicator.startAnimating()
}
public func hideOverlayView() {
activityIndicator.stopAnimating()
overlayView.removeFromSuperview()
}
}
让使用:
LoadingOverlay.shared.showOverlay(self.view)
//To to long tasks
LoadingOverlay.shared.hideOverlayView()
只需为自己创建一个叠加视图,将其添加到父视图并在任务完成后将其删除,例如添加它:
var overlay : UIView? // This should be a class variable
[ ... ]
overlay = UIView(frame: view.frame)
overlay!.backgroundColor = UIColor.blackColor()
overlay!.alpha = 0.8
view.addSubview(overlay!)
删除:
overlay?.removeFromSuperview()
为了补充给定的答案,如果您有时尝试 运行 代码,您可能 运行 会遇到问题。就个人而言,有一次 showOverlay 没有被正确调用(因为我试图进入场景,然后在 viewDidLoad 期间立即调用此函数)。
如果您 运行 遇到与我类似的问题,我建议对代码进行一次修复并改变一种方法。
FIX:将两个代码块作为 dispatch_async 调用的闭包,如下所示:
dispatch_async(dispatch_get_main_queue(),
{ //code });
方法:调用您的代码时,在主队列 上执行dispatch_after 调用以将调用延迟几毫秒。
推理?您只是要求 UI 在 viewDidLoad 期间做太多事情。
如果此解决方案的附录对您有所帮助,我会很高兴。
-乔尔·朗
P.S。解决方案适用于 XCode v6.3.2
对于像我这样迟到的人,我对@Sonrobby 代码做了一些修改。据我了解,@Sonrobby 在每次 showOverlay
调用时将 activity 添加到叠加层。而一些配置可以传给init函数,只让放置在showOverlay
方法上。
我还将叠加层的背景更改为黑色,因为我的应用程序大部分是白色的。
这是代码:
public class LoadingOverlay{
var overlayView : UIView!
var activityIndicator : UIActivityIndicatorView!
class var shared: LoadingOverlay {
struct Static {
static let instance: LoadingOverlay = LoadingOverlay()
}
return Static.instance
}
init(){
self.overlayView = UIView()
self.activityIndicator = UIActivityIndicatorView()
overlayView.frame = CGRectMake(0, 0, 80, 80)
overlayView.backgroundColor = UIColor(white: 0, alpha: 0.7)
overlayView.clipsToBounds = true
overlayView.layer.cornerRadius = 10
overlayView.layer.zPosition = 1
activityIndicator.frame = CGRectMake(0, 0, 40, 40)
activityIndicator.center = CGPointMake(overlayView.bounds.width / 2, overlayView.bounds.height / 2)
activityIndicator.activityIndicatorViewStyle = .WhiteLarge
overlayView.addSubview(activityIndicator)
}
public func showOverlay(view: UIView) {
overlayView.center = view.center
view.addSubview(overlayView)
activityIndicator.startAnimating()
}
public func hideOverlayView() {
activityIndicator.stopAnimating()
overlayView.removeFromSuperview()
}
}
以上答案添加了加载视图,但它不会阻止屏幕上的点击事件,也不会为屏幕的其余部分提供覆盖。您可以通过以下方式实现:
let alert = UIAlertController(title: nil, message: "Please wait...", preferredStyle: .Alert)
alert.view.tintColor = UIColor.blackColor()
let loadingIndicator: UIActivityIndicatorView = UIActivityIndicatorView(frame: CGRectMake(10, 5, 50, 50)) as UIActivityIndicatorView
loadingIndicator.hidesWhenStopped = true
loadingIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.Gray
loadingIndicator.startAnimating();
alert.view.addSubview(loadingIndicator)
presentViewController(alert, animated: true, completion: nil)
Swift 3.0
let alert = UIAlertController(title: nil, message: "Please wait...", preferredStyle: .alert)
let loadingIndicator = UIActivityIndicatorView(frame: CGRect(x: 10, y: 5, width: 50, height: 50))
loadingIndicator.hidesWhenStopped = true
loadingIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
loadingIndicator.startAnimating();
alert.view.addSubview(loadingIndicator)
present(alert, animated: true, completion: nil)
Swift 4.0 及更高版本
let alert = UIAlertController(title: nil, message: "Please wait...", preferredStyle: .alert)
let loadingIndicator = UIActivityIndicatorView(frame: CGRect(x: 10, y: 5, width: 50, height: 50))
loadingIndicator.hidesWhenStopped = true
loadingIndicator.style = UIActivityIndicatorView.Style.gray
loadingIndicator.startAnimating();
alert.view.addSubview(loadingIndicator)
present(alert, animated: true, completion: nil)
你可以隐藏它如下:
dismiss(animated: false, completion: nil)
会显示如下:
Swift 3.
我在他下面的回答中使用了@Lucho 的代码,我将覆盖背景颜色更改为清除并添加了微调器颜色。
public class LoadingOverlay {
var overlayView : UIView!
var activityIndicator : UIActivityIndicatorView!
class var shared: LoadingOverlay {
struct Static {
static let instance: LoadingOverlay = LoadingOverlay()
}
return Static.instance
}
init(){
self.overlayView = UIView()
self.activityIndicator = UIActivityIndicatorView()
overlayView.frame = CGRect(0, 0, 80, 80)
overlayView.backgroundColor = .clear
overlayView.clipsToBounds = true
overlayView.layer.cornerRadius = 10
overlayView.layer.zPosition = 1
activityIndicator.frame = CGRect(0, 0, 40, 40)
activityIndicator.center = CGPoint(overlayView.bounds.width / 2, overlayView.bounds.height / 2)
activityIndicator.activityIndicatorViewStyle = .whiteLarge
activityIndicator.color = .gray
overlayView.addSubview(activityIndicator)
}
public func showOverlay(view: UIView) {
overlayView.center = view.center
view.addSubview(overlayView)
activityIndicator.startAnimating()
}
public func hideOverlayView() {
activityIndicator.stopAnimating()
overlayView.removeFromSuperview()
}
}
我已经创建了一个协议,用于将您自己的视图控制器呈现为叠加层。用法很简单:
class ViewController: UIViewController, OverlayHost {
@IBAction func showOverlayButtonPressed() {
showOverlay(type: YourOverlayViewController.self,
fromStoryboardWithName: "Main")
}
}
结果:
源代码:https://github.com/agordeev/OverlayViewController
相关文章:https://andreygordeev.com/2017/04/18/overlay-view-controller-protocols-swift/
更新了@sonrobby 的回答,通过调整蒙版大小添加了背景视图和方向处理...这可用于简单的东西
public class LoadingOverlay{
var overlayView = UIView()
var activityIndicator = UIActivityIndicatorView()
var bgView = UIView()
class var shared: LoadingOverlay {
struct Static {
static let instance: LoadingOverlay = LoadingOverlay()
}
return Static.instance
}
public func showOverlay(view: UIView) {
bgView.frame = view.frame
bgView.backgroundColor = UIColor.gray
bgView.addSubview(overlayView)
bgView.autoresizingMask = [.flexibleLeftMargin,.flexibleTopMargin,.flexibleRightMargin,.flexibleBottomMargin,.flexibleHeight, .flexibleWidth]
overlayView.frame = CGRect(x: 0, y: 0, width: 80, height: 80)
overlayView.center = view.center
overlayView.autoresizingMask = [.flexibleLeftMargin,.flexibleTopMargin,.flexibleRightMargin,.flexibleBottomMargin]
overlayView.backgroundColor = UIColor.black
overlayView.clipsToBounds = true
overlayView.layer.cornerRadius = 10
activityIndicator.frame = CGRect(x: 0, y: 0, width: 40, height: 40)
activityIndicator.activityIndicatorViewStyle = .whiteLarge
activityIndicator.center = CGPoint(x: overlayView.bounds.width / 2, y: overlayView.bounds.height / 2)
overlayView.addSubview(activityIndicator)
view.addSubview(bgView)
self.activityIndicator.startAnimating()
}
public func hideOverlayView() {
activityIndicator.stopAnimating()
bgView.removeFromSuperview()
}
}
如果您将它添加到 keywindow,它也可以遍历您的导航栏和标签栏...像这样
LoadingOverlay.shared.showOverlay(view: UIApplication.shared.keyWindow!)
模糊背景 + Activity 指标,Swift 5 个例子
extension UIView {
func showBlurLoader() {
let blurLoader = BlurLoader(frame: frame)
self.addSubview(blurLoader)
}
func removeBluerLoader() {
if let blurLoader = subviews.first(where: { [=10=] is BlurLoader }) {
blurLoader.removeFromSuperview()
}
}
}
class BlurLoader: UIView {
var blurEffectView: UIVisualEffectView?
override init(frame: CGRect) {
let blurEffect = UIBlurEffect(style: .dark)
let blurEffectView = UIVisualEffectView(effect: blurEffect)
blurEffectView.frame = frame
blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.blurEffectView = blurEffectView
super.init(frame: frame)
addSubview(blurEffectView)
addLoader()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func addLoader() {
guard let blurEffectView = blurEffectView else { return }
let activityIndicator = UIActivityIndicatorView(style: .whiteLarge)
activityIndicator.frame = CGRect(x: 0, y: 0, width: 50, height: 50)
blurEffectView.contentView.addSubview(activityIndicator)
activityIndicator.center = blurEffectView.contentView.center
activityIndicator.startAnimating()
}
}
使用 ATKit。
参考:
https://aurvan.github.io/atkit-ios-release/index.html
ATProgressOverlay Class
https://aurvan.github.io/atkit-ios-release/helpbook/Classes/ATProgressOverlay.html
代码:
import ATKit
ATProgressOverlay.sharedInstance.show() // Does not show network activity indicator on status bar.
ATProgressOverlay.sharedInstance.show(isNetworkActivity: true) // Shows network activity indicator on status bar.
截图:
Swift 5
class func showUniversalLoadingView(_ show: Bool, loadingText : String = "") {
let existingView = UIApplication.shared.windows[0].viewWithTag(1200)
if show {
if existingView != nil {
return
}
let loadingView = self.makeLoadingView(withFrame: UIScreen.main.bounds, loadingText: loadingText)
loadingView?.tag = 1200
UIApplication.shared.windows[0].addSubview(loadingView!)
} else {
existingView?.removeFromSuperview()
}
}
class func makeLoadingView(withFrame frame: CGRect, loadingText text: String?) -> UIView? {
let loadingView = UIView(frame: frame)
loadingView.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.5)
let activityIndicator = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
//activityIndicator.backgroundColor = UIColor(red:0.16, green:0.17, blue:0.21, alpha:1)
activityIndicator.layer.cornerRadius = 6
activityIndicator.center = loadingView.center
activityIndicator.hidesWhenStopped = true
activityIndicator.style = .white
activityIndicator.startAnimating()
activityIndicator.tag = 100 // 100 for example
loadingView.addSubview(activityIndicator)
if !text!.isEmpty {
let lbl = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 30))
let cpoint = CGPoint(x: activityIndicator.frame.origin.x + activityIndicator.frame.size.width / 2, y: activityIndicator.frame.origin.y + 80)
lbl.center = cpoint
lbl.textColor = UIColor.white
lbl.textAlignment = .center
lbl.text = text
lbl.tag = 1234
loadingView.addSubview(lbl)
}
return loadingView
}
使用
showUniversalLoadingView(true, loadingText: "Downloading Data.......")
showUniversalLoadingView(真)
删除加载程序
showUniversalLoadingView(false)
@Ajinkya Patil 的回答作为参考。 Swift 4.0 及更高版本
这是一个扩展解决方案,可以在所有 viewController 上使用而不会发生冲突。
创建一个加载对话框+ViewContoller.swift
import UIKit
struct ProgressDialog {
static var alert = UIAlertController()
static var progressView = UIProgressView()
static var progressPoint : Float = 0{
didSet{
if(progressPoint == 1){
ProgressDialog.alert.dismiss(animated: true, completion: nil)
}
}
}
}
extension UIViewController{
func LoadingStart(){
ProgressDialog.alert = UIAlertController(title: nil, message: "Please wait...", preferredStyle: .alert)
let loadingIndicator = UIActivityIndicatorView(frame: CGRect(x: 10, y: 5, width: 50, height: 50))
loadingIndicator.hidesWhenStopped = true
loadingIndicator.style = UIActivityIndicatorView.Style.gray
loadingIndicator.startAnimating();
ProgressDialog.alert.view.addSubview(loadingIndicator)
present(ProgressDialog.alert, animated: true, completion: nil)
}
func LoadingStop(){
ProgressDialog.alert.dismiss(animated: true, completion: nil)
}
}
在任何地方调用 ViewController 中的函数。像这样:
self.LoadingStart()
这是停止加载对话框的方法。
self.LoadingStop()
Xamarin.iOS版本:
var alert = UIAlertController.Create(string.Empty, "Please wait...", UIAlertControllerStyle.Alert);
var alertIndicatorView = new UIActivityIndicatorView();
alertIndicatorView.Frame = new CGRect(x: 10, y: 5, width: 50, height: 50);
alertIndicatorView.ActivityIndicatorViewStyle = UIActivityIndicatorViewStyle.Gray;
alertIndicatorView.HidesWhenStopped = true;
alertIndicatorView.StartAnimating();
alert.Add(alertIndicatorView);
controller.PresentViewController(alert, true, null);
如果有人正在寻找用于加载视图的 Lottie 实现,这是我使用@Shourob Datta 解决方案制作的有效解决方案:
import Foundation
import UIKit
import Lottie
public class LogoLoadingAnimation{
class func showUniversalLoadingView(_ show: Bool, loadingText : String = "") {
let existingView = UIApplication.shared.windows[0].viewWithTag(1200)
if show {
if existingView != nil {
return
}
let loadingView = self.makeLoadingView(withFrame: UIScreen.main.bounds, loadingText: loadingText)
loadingView?.tag = 1200
UIApplication.shared.windows[0].addSubview(loadingView!)
} else {
existingView?.removeFromSuperview()
}
}
class func makeLoadingView(withFrame frame: CGRect, loadingText text: String?) -> UIView? {
let gradienView = GradientBackgroundView(frame: frame)
gradienView.startColor = UIColor(red: 255, green: 255, blue: 255, alpha: 1)
gradienView.endColor = UIColor(red: 238, green: 238, blue: 238, alpha: 1)
gradienView.startColor = UIColor(named: "dark") ?? .blue
gradienView.startColor = UIColor(named: "purpuleGrey") ?? .gray
let loadingAnimationView = AnimationView()
gradienView.addSubview(loadingAnimationView)
loadingAnimationView.translatesAutoresizingMaskIntoConstraints = false
loadingAnimationView.centerXAnchor.constraint(equalTo: gradienView.centerXAnchor).isActive = true
loadingAnimationView.centerYAnchor.constraint(equalTo: gradienView.centerYAnchor).isActive = true
loadingAnimationView.animation = UITraitCollection.current.userInterfaceStyle == .dark ? Animation.named("logoLoadingWhite") : Animation.named("logoLoadingBlue")
loadingAnimationView.backgroundBehavior = .pauseAndRestore
loadingAnimationView.contentMode = .scaleAspectFit
loadingAnimationView.loopMode = .loop
loadingAnimationView.play()
return gradienView
}
}
在Swift IOS 应用程序中执行长任务时加载叠加层的示例是什么。从远程服务器加载数据的示例。 我用谷歌搜索但没有找到任何答案。
已更新:
感谢@Sebastian Dressler,这是一种简单的方法。我更新了我的代码,它 运行 很酷
public class LoadingOverlay{
var overlayView = UIView()
var activityIndicator = UIActivityIndicatorView()
class var shared: LoadingOverlay {
struct Static {
static let instance: LoadingOverlay = LoadingOverlay()
}
return Static.instance
}
public func showOverlay(view: UIView) {
overlayView.frame = CGRectMake(0, 0, 80, 80)
overlayView.center = view.center
overlayView.backgroundColor = UIColor(hex: 0x444444, alpha: 0.7)
overlayView.clipsToBounds = true
overlayView.layer.cornerRadius = 10
activityIndicator.frame = CGRectMake(0, 0, 40, 40)
activityIndicator.activityIndicatorViewStyle = .WhiteLarge
activityIndicator.center = CGPointMake(overlayView.bounds.width / 2, overlayView.bounds.height / 2)
overlayView.addSubview(activityIndicator)
view.addSubview(overlayView)
activityIndicator.startAnimating()
}
public func hideOverlayView() {
activityIndicator.stopAnimating()
overlayView.removeFromSuperview()
}
}
让使用:
LoadingOverlay.shared.showOverlay(self.view)
//To to long tasks
LoadingOverlay.shared.hideOverlayView()
只需为自己创建一个叠加视图,将其添加到父视图并在任务完成后将其删除,例如添加它:
var overlay : UIView? // This should be a class variable
[ ... ]
overlay = UIView(frame: view.frame)
overlay!.backgroundColor = UIColor.blackColor()
overlay!.alpha = 0.8
view.addSubview(overlay!)
删除:
overlay?.removeFromSuperview()
为了补充给定的答案,如果您有时尝试 运行 代码,您可能 运行 会遇到问题。就个人而言,有一次 showOverlay 没有被正确调用(因为我试图进入场景,然后在 viewDidLoad 期间立即调用此函数)。
如果您 运行 遇到与我类似的问题,我建议对代码进行一次修复并改变一种方法。
FIX:将两个代码块作为 dispatch_async 调用的闭包,如下所示:
dispatch_async(dispatch_get_main_queue(),
{ //code });
方法:调用您的代码时,在主队列 上执行dispatch_after 调用以将调用延迟几毫秒。
推理?您只是要求 UI 在 viewDidLoad 期间做太多事情。
如果此解决方案的附录对您有所帮助,我会很高兴。
-乔尔·朗
P.S。解决方案适用于 XCode v6.3.2
对于像我这样迟到的人,我对@Sonrobby 代码做了一些修改。据我了解,@Sonrobby 在每次 showOverlay
调用时将 activity 添加到叠加层。而一些配置可以传给init函数,只让放置在showOverlay
方法上。
我还将叠加层的背景更改为黑色,因为我的应用程序大部分是白色的。
这是代码:
public class LoadingOverlay{
var overlayView : UIView!
var activityIndicator : UIActivityIndicatorView!
class var shared: LoadingOverlay {
struct Static {
static let instance: LoadingOverlay = LoadingOverlay()
}
return Static.instance
}
init(){
self.overlayView = UIView()
self.activityIndicator = UIActivityIndicatorView()
overlayView.frame = CGRectMake(0, 0, 80, 80)
overlayView.backgroundColor = UIColor(white: 0, alpha: 0.7)
overlayView.clipsToBounds = true
overlayView.layer.cornerRadius = 10
overlayView.layer.zPosition = 1
activityIndicator.frame = CGRectMake(0, 0, 40, 40)
activityIndicator.center = CGPointMake(overlayView.bounds.width / 2, overlayView.bounds.height / 2)
activityIndicator.activityIndicatorViewStyle = .WhiteLarge
overlayView.addSubview(activityIndicator)
}
public func showOverlay(view: UIView) {
overlayView.center = view.center
view.addSubview(overlayView)
activityIndicator.startAnimating()
}
public func hideOverlayView() {
activityIndicator.stopAnimating()
overlayView.removeFromSuperview()
}
}
以上答案添加了加载视图,但它不会阻止屏幕上的点击事件,也不会为屏幕的其余部分提供覆盖。您可以通过以下方式实现:
let alert = UIAlertController(title: nil, message: "Please wait...", preferredStyle: .Alert)
alert.view.tintColor = UIColor.blackColor()
let loadingIndicator: UIActivityIndicatorView = UIActivityIndicatorView(frame: CGRectMake(10, 5, 50, 50)) as UIActivityIndicatorView
loadingIndicator.hidesWhenStopped = true
loadingIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.Gray
loadingIndicator.startAnimating();
alert.view.addSubview(loadingIndicator)
presentViewController(alert, animated: true, completion: nil)
Swift 3.0
let alert = UIAlertController(title: nil, message: "Please wait...", preferredStyle: .alert)
let loadingIndicator = UIActivityIndicatorView(frame: CGRect(x: 10, y: 5, width: 50, height: 50))
loadingIndicator.hidesWhenStopped = true
loadingIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
loadingIndicator.startAnimating();
alert.view.addSubview(loadingIndicator)
present(alert, animated: true, completion: nil)
Swift 4.0 及更高版本
let alert = UIAlertController(title: nil, message: "Please wait...", preferredStyle: .alert)
let loadingIndicator = UIActivityIndicatorView(frame: CGRect(x: 10, y: 5, width: 50, height: 50))
loadingIndicator.hidesWhenStopped = true
loadingIndicator.style = UIActivityIndicatorView.Style.gray
loadingIndicator.startAnimating();
alert.view.addSubview(loadingIndicator)
present(alert, animated: true, completion: nil)
你可以隐藏它如下:
dismiss(animated: false, completion: nil)
会显示如下:
Swift 3.
我在他下面的回答中使用了@Lucho 的代码,我将覆盖背景颜色更改为清除并添加了微调器颜色。
public class LoadingOverlay {
var overlayView : UIView!
var activityIndicator : UIActivityIndicatorView!
class var shared: LoadingOverlay {
struct Static {
static let instance: LoadingOverlay = LoadingOverlay()
}
return Static.instance
}
init(){
self.overlayView = UIView()
self.activityIndicator = UIActivityIndicatorView()
overlayView.frame = CGRect(0, 0, 80, 80)
overlayView.backgroundColor = .clear
overlayView.clipsToBounds = true
overlayView.layer.cornerRadius = 10
overlayView.layer.zPosition = 1
activityIndicator.frame = CGRect(0, 0, 40, 40)
activityIndicator.center = CGPoint(overlayView.bounds.width / 2, overlayView.bounds.height / 2)
activityIndicator.activityIndicatorViewStyle = .whiteLarge
activityIndicator.color = .gray
overlayView.addSubview(activityIndicator)
}
public func showOverlay(view: UIView) {
overlayView.center = view.center
view.addSubview(overlayView)
activityIndicator.startAnimating()
}
public func hideOverlayView() {
activityIndicator.stopAnimating()
overlayView.removeFromSuperview()
}
}
我已经创建了一个协议,用于将您自己的视图控制器呈现为叠加层。用法很简单:
class ViewController: UIViewController, OverlayHost {
@IBAction func showOverlayButtonPressed() {
showOverlay(type: YourOverlayViewController.self,
fromStoryboardWithName: "Main")
}
}
结果:
源代码:https://github.com/agordeev/OverlayViewController
相关文章:https://andreygordeev.com/2017/04/18/overlay-view-controller-protocols-swift/
更新了@sonrobby 的回答,通过调整蒙版大小添加了背景视图和方向处理...这可用于简单的东西
public class LoadingOverlay{
var overlayView = UIView()
var activityIndicator = UIActivityIndicatorView()
var bgView = UIView()
class var shared: LoadingOverlay {
struct Static {
static let instance: LoadingOverlay = LoadingOverlay()
}
return Static.instance
}
public func showOverlay(view: UIView) {
bgView.frame = view.frame
bgView.backgroundColor = UIColor.gray
bgView.addSubview(overlayView)
bgView.autoresizingMask = [.flexibleLeftMargin,.flexibleTopMargin,.flexibleRightMargin,.flexibleBottomMargin,.flexibleHeight, .flexibleWidth]
overlayView.frame = CGRect(x: 0, y: 0, width: 80, height: 80)
overlayView.center = view.center
overlayView.autoresizingMask = [.flexibleLeftMargin,.flexibleTopMargin,.flexibleRightMargin,.flexibleBottomMargin]
overlayView.backgroundColor = UIColor.black
overlayView.clipsToBounds = true
overlayView.layer.cornerRadius = 10
activityIndicator.frame = CGRect(x: 0, y: 0, width: 40, height: 40)
activityIndicator.activityIndicatorViewStyle = .whiteLarge
activityIndicator.center = CGPoint(x: overlayView.bounds.width / 2, y: overlayView.bounds.height / 2)
overlayView.addSubview(activityIndicator)
view.addSubview(bgView)
self.activityIndicator.startAnimating()
}
public func hideOverlayView() {
activityIndicator.stopAnimating()
bgView.removeFromSuperview()
}
}
如果您将它添加到 keywindow,它也可以遍历您的导航栏和标签栏...像这样
LoadingOverlay.shared.showOverlay(view: UIApplication.shared.keyWindow!)
模糊背景 + Activity 指标,Swift 5 个例子
extension UIView {
func showBlurLoader() {
let blurLoader = BlurLoader(frame: frame)
self.addSubview(blurLoader)
}
func removeBluerLoader() {
if let blurLoader = subviews.first(where: { [=10=] is BlurLoader }) {
blurLoader.removeFromSuperview()
}
}
}
class BlurLoader: UIView {
var blurEffectView: UIVisualEffectView?
override init(frame: CGRect) {
let blurEffect = UIBlurEffect(style: .dark)
let blurEffectView = UIVisualEffectView(effect: blurEffect)
blurEffectView.frame = frame
blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.blurEffectView = blurEffectView
super.init(frame: frame)
addSubview(blurEffectView)
addLoader()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func addLoader() {
guard let blurEffectView = blurEffectView else { return }
let activityIndicator = UIActivityIndicatorView(style: .whiteLarge)
activityIndicator.frame = CGRect(x: 0, y: 0, width: 50, height: 50)
blurEffectView.contentView.addSubview(activityIndicator)
activityIndicator.center = blurEffectView.contentView.center
activityIndicator.startAnimating()
}
}
使用 ATKit。
参考: https://aurvan.github.io/atkit-ios-release/index.html
ATProgressOverlay Class https://aurvan.github.io/atkit-ios-release/helpbook/Classes/ATProgressOverlay.html
代码:
import ATKit
ATProgressOverlay.sharedInstance.show() // Does not show network activity indicator on status bar.
ATProgressOverlay.sharedInstance.show(isNetworkActivity: true) // Shows network activity indicator on status bar.
截图:
Swift 5
class func showUniversalLoadingView(_ show: Bool, loadingText : String = "") {
let existingView = UIApplication.shared.windows[0].viewWithTag(1200)
if show {
if existingView != nil {
return
}
let loadingView = self.makeLoadingView(withFrame: UIScreen.main.bounds, loadingText: loadingText)
loadingView?.tag = 1200
UIApplication.shared.windows[0].addSubview(loadingView!)
} else {
existingView?.removeFromSuperview()
}
}
class func makeLoadingView(withFrame frame: CGRect, loadingText text: String?) -> UIView? {
let loadingView = UIView(frame: frame)
loadingView.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.5)
let activityIndicator = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
//activityIndicator.backgroundColor = UIColor(red:0.16, green:0.17, blue:0.21, alpha:1)
activityIndicator.layer.cornerRadius = 6
activityIndicator.center = loadingView.center
activityIndicator.hidesWhenStopped = true
activityIndicator.style = .white
activityIndicator.startAnimating()
activityIndicator.tag = 100 // 100 for example
loadingView.addSubview(activityIndicator)
if !text!.isEmpty {
let lbl = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 30))
let cpoint = CGPoint(x: activityIndicator.frame.origin.x + activityIndicator.frame.size.width / 2, y: activityIndicator.frame.origin.y + 80)
lbl.center = cpoint
lbl.textColor = UIColor.white
lbl.textAlignment = .center
lbl.text = text
lbl.tag = 1234
loadingView.addSubview(lbl)
}
return loadingView
}
使用
showUniversalLoadingView(true, loadingText: "Downloading Data.......")
showUniversalLoadingView(真)
删除加载程序
showUniversalLoadingView(false)
@Ajinkya Patil 的回答作为参考。 Swift 4.0 及更高版本
这是一个扩展解决方案,可以在所有 viewController 上使用而不会发生冲突。
创建一个加载对话框+ViewContoller.swift
import UIKit
struct ProgressDialog {
static var alert = UIAlertController()
static var progressView = UIProgressView()
static var progressPoint : Float = 0{
didSet{
if(progressPoint == 1){
ProgressDialog.alert.dismiss(animated: true, completion: nil)
}
}
}
}
extension UIViewController{
func LoadingStart(){
ProgressDialog.alert = UIAlertController(title: nil, message: "Please wait...", preferredStyle: .alert)
let loadingIndicator = UIActivityIndicatorView(frame: CGRect(x: 10, y: 5, width: 50, height: 50))
loadingIndicator.hidesWhenStopped = true
loadingIndicator.style = UIActivityIndicatorView.Style.gray
loadingIndicator.startAnimating();
ProgressDialog.alert.view.addSubview(loadingIndicator)
present(ProgressDialog.alert, animated: true, completion: nil)
}
func LoadingStop(){
ProgressDialog.alert.dismiss(animated: true, completion: nil)
}
}
在任何地方调用 ViewController 中的函数。像这样:
self.LoadingStart()
这是停止加载对话框的方法。
self.LoadingStop()
Xamarin.iOS版本:
var alert = UIAlertController.Create(string.Empty, "Please wait...", UIAlertControllerStyle.Alert);
var alertIndicatorView = new UIActivityIndicatorView();
alertIndicatorView.Frame = new CGRect(x: 10, y: 5, width: 50, height: 50);
alertIndicatorView.ActivityIndicatorViewStyle = UIActivityIndicatorViewStyle.Gray;
alertIndicatorView.HidesWhenStopped = true;
alertIndicatorView.StartAnimating();
alert.Add(alertIndicatorView);
controller.PresentViewController(alert, true, null);
如果有人正在寻找用于加载视图的 Lottie 实现,这是我使用@Shourob Datta 解决方案制作的有效解决方案:
import Foundation
import UIKit
import Lottie
public class LogoLoadingAnimation{
class func showUniversalLoadingView(_ show: Bool, loadingText : String = "") {
let existingView = UIApplication.shared.windows[0].viewWithTag(1200)
if show {
if existingView != nil {
return
}
let loadingView = self.makeLoadingView(withFrame: UIScreen.main.bounds, loadingText: loadingText)
loadingView?.tag = 1200
UIApplication.shared.windows[0].addSubview(loadingView!)
} else {
existingView?.removeFromSuperview()
}
}
class func makeLoadingView(withFrame frame: CGRect, loadingText text: String?) -> UIView? {
let gradienView = GradientBackgroundView(frame: frame)
gradienView.startColor = UIColor(red: 255, green: 255, blue: 255, alpha: 1)
gradienView.endColor = UIColor(red: 238, green: 238, blue: 238, alpha: 1)
gradienView.startColor = UIColor(named: "dark") ?? .blue
gradienView.startColor = UIColor(named: "purpuleGrey") ?? .gray
let loadingAnimationView = AnimationView()
gradienView.addSubview(loadingAnimationView)
loadingAnimationView.translatesAutoresizingMaskIntoConstraints = false
loadingAnimationView.centerXAnchor.constraint(equalTo: gradienView.centerXAnchor).isActive = true
loadingAnimationView.centerYAnchor.constraint(equalTo: gradienView.centerYAnchor).isActive = true
loadingAnimationView.animation = UITraitCollection.current.userInterfaceStyle == .dark ? Animation.named("logoLoadingWhite") : Animation.named("logoLoadingBlue")
loadingAnimationView.backgroundBehavior = .pauseAndRestore
loadingAnimationView.contentMode = .scaleAspectFit
loadingAnimationView.loopMode = .loop
loadingAnimationView.play()
return gradienView
}
}