如何在带有Swift的iOS 8上显示带有文本的活动指示器?


Answers:


130

Xcode 9.0•Swift 4.0


import UIKit
class ViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
    @IBOutlet weak var imageView: UIImageView!
    @IBOutlet weak var filterButton: UIButton!
    @IBOutlet weak var saveButton: UIButton!
    let destinationUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
        .appendingPathComponent("filteredImage.png")
    let imagePicker = UIImagePickerController()
    let messageFrame = UIView()
    var activityIndicator = UIActivityIndicatorView()
    var strLabel = UILabel()
    let effectView = UIVisualEffectView(effect: UIBlurEffect(style: .dark))
    func activityIndicator(_ title: String) {
        strLabel.removeFromSuperview()
        activityIndicator.removeFromSuperview()
        effectView.removeFromSuperview()
        strLabel = UILabel(frame: CGRect(x: 50, y: 0, width: 160, height: 46))
        strLabel.text = title
        strLabel.font = .systemFont(ofSize: 14, weight: .medium)
        strLabel.textColor = UIColor(white: 0.9, alpha: 0.7)
        effectView.frame = CGRect(x: view.frame.midX - strLabel.frame.width/2, y: view.frame.midY - strLabel.frame.height/2 , width: 160, height: 46)
        effectView.layer.cornerRadius = 15
        effectView.layer.masksToBounds = true
        activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .white)
        activityIndicator.frame = CGRect(x: 0, y: 0, width: 46, height: 46)
        activityIndicator.startAnimating()
        effectView.contentView.addSubview(activityIndicator)
        effectView.contentView.addSubview(strLabel)
        view.addSubview(effectView)
    }
    func saveImage() {
        do {
            try imageView.image?.data?.write(to: destinationUrl, options: .atomic)
            print("file saved")
        } catch {
            print(error)
        }
    }        
    func applyFilterToImage() {
        imageView.image = imageView.image?.applying(contrast: 1.5)
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        guard let url = URL(string: "https://upload.wikimedia.org/wikipedia/commons/a/a8/VST_images_the_Lagoon_Nebula.jpg"), let data = try? Data(contentsOf: url), let image = UIImage(data: data) else { return }
        view.backgroundColor = UIColor(white: 0, alpha: 1)
        imageView.image = image
    }
    @IBAction func startSavingImage(_ sender: AnyObject) {
        saveButton.isEnabled = false
        filterButton.isEnabled = false
        activityIndicator("Saving Image")
        DispatchQueue.main.async {
            self.saveImage()
            DispatchQueue.main.async {
                self.effectView.removeFromSuperview()
                self.saveButton.isEnabled = true
                self.filterButton.isEnabled = true
            }
        }
    }
    @IBAction func filterAction(_ sender: AnyObject) {
        filterButton.isEnabled = false
        saveButton.isEnabled = false
        activityIndicator("Applying Filter")
        DispatchQueue.main.async {
            self.applyFilterToImage()
            DispatchQueue.main.async {
                self.effectView.removeFromSuperview()
                self.filterButton.isEnabled = true
                self.saveButton.isEnabled = true
            }
        }
    }
    @IBAction func cameraAction(_ sender: AnyObject) {
        if UIImagePickerController.isSourceTypeAvailable(.camera) {
            imagePicker.delegate = self
            imagePicker.sourceType = .camera
            present(imagePicker, animated: true)
        }
    }
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingImage image: UIImage!, editingInfo: [AnyHashable: Any]!) {
        dismiss(animated: true, completion: nil)
        imageView.image = image
    }
}

extension Data {
    var image: UIImage? { return UIImage(data: self) }
}

extension UIImage {
    var data: Data? { return UIImagePNGRepresentation(self) }
    func applying(contrast value: NSNumber) -> UIImage? {
        guard let ciImage = CIImage(image: self)?.applyingFilter("CIColorControls", withInputParameters: [kCIInputContrastKey: value]) else { return nil }
        UIGraphicsBeginImageContextWithOptions(size, false, scale)
        defer { UIGraphicsEndImageContext() }
        UIImage(ciImage: ciImage).draw(in: CGRect(origin: .zero, size: size))
        return UIGraphicsGetImageFromCurrentImageContext()
    }
}


我将progressBarDisplayer修改为一个类,并通过将视图作为参数传递来显示它。您将如何识别已经添加的progressBarDisplayer,并在完成所有加载后将其删除?
simplexity

1
@simplexity随时打开一个新问题,在此处发布您的实际代码,并让我知道您是否希望我看一下它。
Leo Dabus

感谢您的答复!我实际上最终将创建的视图存储在变量中,并将其引用removeFromSuperview并设置为nil。不知道这是否是最好的方法,但是上面设置的代码对您有很大帮助!
simplexity

对Objective-C有用吗?
Artem Zaytsev

@KrishnaMeena什么不起作用?您在哪一行中遇到什么错误?
Leo Dabus

117

在Esq的答案起作用的同时,我添加了自己的实现,该实现通过将视图分为自己的类来更符合良好的组件体系结构。它还使用iOS 8中引入的动态模糊。

这是我的图像背景外观:

在此处输入图片说明

用于此目的的代码封装在其自己的UIView类中,这意味着您可以在需要时重用它。

为Swift 3更新

用法

func viewDidLoad() {
  super.viewDidLoad()

  // Create and add the view to the screen.
  let progressHUD = ProgressHUD(text: "Saving Photo")
  self.view.addSubview(progressHUD)
  // All done!

  self.view.backgroundColor = UIColor.black
}

UIView代码

import UIKit

class ProgressHUD: UIVisualEffectView {

  var text: String? {
    didSet {
      label.text = text
    }
  }

  let activityIndictor: UIActivityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.gray)
  let label: UILabel = UILabel()
  let blurEffect = UIBlurEffect(style: .light)
  let vibrancyView: UIVisualEffectView

  init(text: String) {
    self.text = text
    self.vibrancyView = UIVisualEffectView(effect: UIVibrancyEffect(blurEffect: blurEffect))
    super.init(effect: blurEffect)
    self.setup()
  }

  required init?(coder aDecoder: NSCoder) {
    self.text = ""
    self.vibrancyView = UIVisualEffectView(effect: UIVibrancyEffect(blurEffect: blurEffect))
    super.init(coder: aDecoder)
    self.setup()
  }

  func setup() {
    contentView.addSubview(vibrancyView)
    contentView.addSubview(activityIndictor)
    contentView.addSubview(label)
    activityIndictor.startAnimating()
  }

  override func didMoveToSuperview() {
    super.didMoveToSuperview()

    if let superview = self.superview {

      let width = superview.frame.size.width / 2.3
      let height: CGFloat = 50.0
      self.frame = CGRect(x: superview.frame.size.width / 2 - width / 2,
                      y: superview.frame.height / 2 - height / 2,
                      width: width,
                      height: height)
      vibrancyView.frame = self.bounds

      let activityIndicatorSize: CGFloat = 40
      activityIndictor.frame = CGRect(x: 5,
                                      y: height / 2 - activityIndicatorSize / 2,
                                      width: activityIndicatorSize,
                                      height: activityIndicatorSize)

      layer.cornerRadius = 8.0
      layer.masksToBounds = true
      label.text = text
      label.textAlignment = NSTextAlignment.center
      label.frame = CGRect(x: activityIndicatorSize + 5,
                           y: 0,
                           width: width - activityIndicatorSize - 15,
                           height: height)
      label.textColor = UIColor.gray
      label.font = UIFont.boldSystemFont(ofSize: 16)
    }
  }

  func show() {
    self.isHidden = false
  }

  func hide() {
    self.isHidden = true
  }
}

迅捷2

这样的用法示例如下:

override func viewDidLoad() {
    super.viewDidLoad()

    // Create and add the view to the screen.
    let progressHUD = ProgressHUD(text: "Saving Photo")
    self.view.addSubview(progressHUD)
    // All done!

    self.view.backgroundColor = UIColor.blackColor()
}

这是UIView代码:

import UIKit

class ProgressHUD: UIVisualEffectView {

    var text: String? {
        didSet {
            label.text = text
        }
    }
    let activityIndictor: UIActivityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.White)
    let label: UILabel = UILabel()
    let blurEffect = UIBlurEffect(style: .Light)
    let vibrancyView: UIVisualEffectView

    init(text: String) {
        self.text = text
        self.vibrancyView = UIVisualEffectView(effect: UIVibrancyEffect(forBlurEffect: blurEffect))
        super.init(effect: blurEffect)
        self.setup()
    }

    required init(coder aDecoder: NSCoder) {
        self.text = ""
        self.vibrancyView = UIVisualEffectView(effect: UIVibrancyEffect(forBlurEffect: blurEffect))
        super.init(coder: aDecoder)
        self.setup()

    }

    func setup() {
        contentView.addSubview(vibrancyView)
        vibrancyView.contentView.addSubview(activityIndictor)
        vibrancyView.contentView.addSubview(label)
        activityIndictor.startAnimating()
    }

    override func didMoveToSuperview() {
        super.didMoveToSuperview()

        if let superview = self.superview {

            let width = superview.frame.size.width / 2.3
            let height: CGFloat = 50.0
            self.frame = CGRectMake(superview.frame.size.width / 2 - width / 2,
                superview.frame.height / 2 - height / 2,
                width,
                height)
            vibrancyView.frame = self.bounds

            let activityIndicatorSize: CGFloat = 40
            activityIndictor.frame = CGRectMake(5, height / 2 - activityIndicatorSize / 2,
                activityIndicatorSize,
                activityIndicatorSize)

            layer.cornerRadius = 8.0
            layer.masksToBounds = true
            label.text = text
            label.textAlignment = NSTextAlignment.Center
            label.frame = CGRectMake(activityIndicatorSize + 5, 0, width - activityIndicatorSize - 15, height)
            label.textColor = UIColor.grayColor()
            label.font = UIFont.boldSystemFontOfSize(16)
        }
    }

    func show() {
        self.hidden = false
    }

    func hide() {
        self.hidden = true
    }
}

希望对您有所帮助,请随时在任何需要的地方使用此代码。


嗨,感谢您的代码,但仍然遇到错误,按照建议声明un viewDidLoad并得到以下错误:类'_TtC22LabMaternalhaematology11ProgressHUD'的0x2dd698无法实现didNotRecognizeSelector:-中止(lldb)。需要能够显示和隐藏在闭包内,因此需要对对象实例进行引用ref
dancebush 2015年

@dancingbush你曾经想过吗?由于某种原因,我现在遇到相同的错误,但并没有改变刚开始发生的错误
Tyler

1
这绝对是最好的方法(可重用的类),但是标签文本和微调框太轻,无法正确显示。而label.color = <color>被忽略:-S
Pylinux

1
@ElliottMinns就是我的意思(ig伪代码)。如果我这样做label.textColor = UIColor.greenColor()对文字颜色没有影响。
Pylinux

2
@ElliottMinns这不会出现在屏幕中央(在iPhone 7 Plus模拟器中经过测试)
Dee

19

以下是此代码的外观:

在此处输入图片说明

这是我的拖放代码:

var boxView = UIView()

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    view.backgroundColor = UIColor.blackColor()
    addSavingPhotoView()

    //Custom button to test this app
    var button = UIButton(frame: CGRect(x: 20, y: 20, width: 20, height: 20))
    button.backgroundColor = UIColor.redColor()
    button.addTarget(self, action: "buttonAction:", forControlEvents: UIControlEvents.TouchUpInside)

    view.addSubview(button)
}

func addSavingPhotoView() {
    // You only need to adjust this frame to move it anywhere you want
    boxView = UIView(frame: CGRect(x: view.frame.midX - 90, y: view.frame.midY - 25, width: 180, height: 50))
    boxView.backgroundColor = UIColor.whiteColor()
    boxView.alpha = 0.8
    boxView.layer.cornerRadius = 10

    //Here the spinnier is initialized
    var activityView = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.Gray)
    activityView.frame = CGRect(x: 0, y: 0, width: 50, height: 50)
    activityView.startAnimating()

    var textLabel = UILabel(frame: CGRect(x: 60, y: 0, width: 200, height: 50))
    textLabel.textColor = UIColor.grayColor()
    textLabel.text = "Saving Photo"

    boxView.addSubview(activityView)
    boxView.addSubview(textLabel)

    view.addSubview(boxView)
}

func buttonAction(sender:UIButton!) {
    //When button is pressed it removes the boxView from screen
    boxView.removeFromSuperview()
}

这是此的开源版本:https : //github.com/goktugyil/CozyLoadingActivity



10

根据我之前的回答,这是一个使用自定义类的更优雅的解决方案:

首先定义此自定义类:

import UIKit
import Foundation

class ActivityIndicatorView
{
    var view: UIView!

var activityIndicator: UIActivityIndicatorView!

var title: String!

init(title: String, center: CGPoint, width: CGFloat = 200.0, height: CGFloat = 50.0)
{
    self.title = title

    let x = center.x - width/2.0
    let y = center.y - height/2.0

    self.view = UIView(frame: CGRect(x: x, y: y, width: width, height: height))
    self.view.backgroundColor = UIColor(red: 255.0/255.0, green: 204.0/255.0, blue: 51.0/255.0, alpha: 0.5)
    self.view.layer.cornerRadius = 10

    self.activityIndicator = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
    self.activityIndicator.color = UIColor.blackColor()
    self.activityIndicator.hidesWhenStopped = false

    let titleLabel = UILabel(frame: CGRect(x: 60, y: 0, width: 200, height: 50))
    titleLabel.text = title
    titleLabel.textColor = UIColor.blackColor()

    self.view.addSubview(self.activityIndicator)
    self.view.addSubview(titleLabel)
}

func getViewActivityIndicator() -> UIView
{
    return self.view
}

func startAnimating()
{
    self.activityIndicator.startAnimating()
    UIApplication.sharedApplication().beginIgnoringInteractionEvents()
}

func stopAnimating()
{
    self.activityIndicator.stopAnimating()
    UIApplication.sharedApplication().endIgnoringInteractionEvents()

    self.view.removeFromSuperview()
}
//end
}

现在在您的UIViewController课程上:

var activityIndicatorView: ActivityIndicatorView!

override func viewDidLoad()
{
    super.viewDidLoad()

    self.activityIndicatorView = ActivityIndicatorView(title: "Processing...", center: self.view.center)
    self.view.addSubview(self.activityIndicatorView.getViewActivityIndicator())

}

func doSomething()
{
    self.activityIndicatorView.startAnimating()
    UIApplication.sharedApplication().beginIgnoringInteractionEvents()

    //do something here that will taking time

    self.activityIndicatorView.stopAnimating()
}

快速提问。为什么要在doSomething()-> self.activityIndi​​catorView.startAnimating()中调用UIApplication.sharedApplication()。beginIgnoringInteractionEvents()两次,然后在调用之后立即调用?
杰森·福利亚

6

对于Swift 3

在此处输入图片说明

用法

class LoginTVC: UITableViewController {
    var loadingView : LoadingView!

    override func viewDidLoad() {
        super.viewDidLoad()

        // CASE 1: To Show loadingView on load

        loadingView = LoadingView(uiView: view, message: "Sending you verification code")
    }

    // CASE 2: To show loadingView on click of a button

    @IBAction func showLoadingView(_ sender: UIButton) {
        if let loaderView = loadingView{ // If loadingView already exists
            if loaderView.isHidden() {
                loaderView.show()  // To show activity indicator
            }
        }
        else{
            loadingView = LoadingView(uiView: view, message: "Sending you verification code")
         }
    }
}

    // CASE 3: To hide LoadingView on click of a button

    @IBAction func hideLoadingView(_ sender: UIButton) {
        if let loaderView = loadingView{ // If loadingView already exists 
            self.loadingView.hide()   
        }
    }
}

LoadingView类别

class LoadingView {

    let uiView          :   UIView
    let message         :   String
    let messageLabel    =   UILabel()

    let loadingSV       =   UIStackView()
    let loadingView     =   UIView()
    let activityIndicator: UIActivityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.gray)

    init(uiView: UIView, message: String) {
        self.uiView     =   uiView
        self.message    =   message
        self.setup()
    }

    func setup(){
        let viewWidth   = uiView.bounds.width
        let viewHeight  = uiView.bounds.height

        // Configuring the message label
        messageLabel.text             = message
        messageLabel.textColor        = UIColor.darkGray
        messageLabel.textAlignment    = .center
        messageLabel.numberOfLines    = 3
        messageLabel.lineBreakMode    = .byWordWrapping

        // Creating stackView to center and align Label and Activity Indicator
        loadingSV.axis          = .vertical
        loadingSV.distribution  = .equalSpacing
        loadingSV.alignment     = .center
        loadingSV.addArrangedSubview(activityIndicator)
        loadingSV.addArrangedSubview(messageLabel)

        // Creating loadingView, this acts as a background for label and activityIndicator
        loadingView.frame           = uiView.frame
        loadingView.center          = uiView.center
        loadingView.backgroundColor = UIColor.darkGray.withAlphaComponent(0.3)
        loadingView.clipsToBounds   = true

        // Disabling auto constraints
        loadingSV.translatesAutoresizingMaskIntoConstraints = false

        // Adding subviews
        loadingView.addSubview(loadingSV)
        uiView.addSubview(loadingView)
        activityIndicator.startAnimating()

        // Views dictionary
        let views = [
            "loadingSV": loadingSV
        ]

        // Constraints for loadingSV
        uiView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-[loadingSV(300)]-|", options: [], metrics: nil, views: views))
        uiView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-\(viewHeight / 3)-[loadingSV(50)]-|", options: [], metrics: nil, views: views))
    }

    // Call this method to hide loadingView
    func show() {
        loadingView.isHidden = false
    }

    // Call this method to show loadingView
    func hide(){
        loadingView.isHidden = true
    }

    // Call this method to check if loading view already exists
    func isHidden() -> Bool{
        if loadingView.isHidden == false{
            return false
        }
        else{
            return true
        }
    }
}

5

您可以创建自己的。例如:

创建一个带有白色背景和圆角的视图:

var view = UIView(frame: CGRect(x: 0, y: 0, width: 300, height: 50))
view.backgroundColor = UIColor.whiteColor()
view.layer.cornerRadius = 10

添加两个子视图aUIActivityIndicatorView和a UILabel

var wait = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
wait.color = UIColor.blackColor()
wait.hidesWhenStopped = false


var text = UILabel(frame: CGRect(x: 60, y: 0, width: 200, height: 50))
text.text = "Processing..."

view.addSubview(wait)
view.addSubview(text)

您的代码很容易理解,但我行不通。我的应用程序中有一个按钮可以保存图像。我只是将这段代码粘贴到了IBAction我的视图控制器中,却没有发生任何事情
rodrigoalvesvieira 2015年

您需要view在尝试显示微调器的地方添加为视图的子视图。另外,看起来苹果的版本可能正在使用UIVisualEffectView来模糊其背后的背景。
Zev Eisenberg 2015年

请参阅Zev的评论。我的代码创建了视图,但是您需要将其放置在某个地方。您可能想对尺寸做得更好。
MirekE 2015年

好的,它在这里有效,但是我更改了它wait.hidesWhenStopped = false。问题:如何隐藏对象view
Thiago Arreguy 2015年

答案:view.removeFromSuperview()
Thiago Arreguy

5

对于活动指示器,最好创建一个自定义类。

而不是在每个UIViewController.Subclass中创建UIActivityIndi​​cator,然后从任何UIViewController中使用UIView。

为Swift 5.0更新:

import UIKit
import Foundation
class ProgressIndicator: UIView {

var indicatorColor:UIColor
var loadingViewColor:UIColor
var loadingMessage:String
var messageFrame = UIView()
var activityIndicator = UIActivityIndicatorView()

init(inview:UIView,loadingViewColor:UIColor,indicatorColor:UIColor,msg:String){

    self.indicatorColor = indicatorColor
    self.loadingViewColor = loadingViewColor
    self.loadingMessage = msg
    super.init(frame: CGRect(x: inview.frame.midX - 90, y: inview.frame.midY - 250 , width: 180, height: 50))
    initalizeCustomIndicator()

}
convenience init(inview:UIView) {

    self.init(inview: inview,loadingViewColor: UIColor.brown,indicatorColor:UIColor.black, msg: "Loading..")
}
convenience init(inview:UIView,messsage:String) {

    self.init(inview: inview,loadingViewColor: UIColor.brown,indicatorColor:UIColor.black, msg: messsage)
}

required init?(coder aDecoder: NSCoder) {

    fatalError("init(coder:) has not been implemented")
}

func initalizeCustomIndicator(){

    messageFrame.frame = self.bounds
    activityIndicator = UIActivityIndicatorView(style: UIActivityIndicatorView.Style.medium)
    activityIndicator.tintColor = indicatorColor
    activityIndicator.hidesWhenStopped = true
    activityIndicator.frame = CGRect(x: self.bounds.origin.x + 6, y: 0, width: 20, height: 50)
    print(activityIndicator.frame)
    let strLabel = UILabel(frame:CGRect(x: self.bounds.origin.x + 30, y: 0, width: self.bounds.width - (self.bounds.origin.x + 30) , height: 50))
    strLabel.text = loadingMessage
    strLabel.adjustsFontSizeToFitWidth = true
    strLabel.textColor = UIColor.white
    messageFrame.layer.cornerRadius = 15
    messageFrame.backgroundColor = loadingViewColor
    messageFrame.alpha = 0.8
    messageFrame.addSubview(activityIndicator)
    messageFrame.addSubview(strLabel)


}

func  start(){
    //check if view is already there or not..if again started
    if !self.subviews.contains(messageFrame){

        activityIndicator.startAnimating()
        self.addSubview(messageFrame)

    }
}

func stop(){

    if self.subviews.contains(messageFrame){

        activityIndicator.stopAnimating()
        messageFrame.removeFromSuperview()

    }
}
}

将此类放在您的项目中,然后从任何ViewController调用为

var indicator:ProgressIndicator?
override func viewDidLoad() {
    super.viewDidLoad()

    //indicator = ProgressIndicator(inview: self.view,messsage: "Hello from Nepal..")
    //self.view.addSubview(indicator!)
    //OR
    indicator = ProgressIndicator(inview:self.view,loadingViewColor: UIColor.grayColor(), indicatorColor: UIColor.blackColor(), msg: "Landing within minutes,Please hold tight..")
    self.view.addSubview(indicator!)

}

@IBAction func startBtn(sender: AnyObject) {
    indicator!.start()
}


@IBAction func stopBtn(sender: AnyObject) {
    indicator!.stop()
}

4

基于“ MirekE”的答案,这里是我现在测试的代码及其工作原理:

var activityIndicator: UIActivityIndicatorView!

var viewActivityIndicator: UIView!

override func viewDidLoad()
{
    super.viewDidLoad()

    let width: CGFloat = 200.0
    let height: CGFloat = 50.0
    let x = self.view.frame.width/2.0 - width/2.0
    let y = self.view.frame.height/2.0 - height/2.0

    self.viewActivityIndicator = UIView(frame: CGRect(x: x, y: y, width: width, height: height))
    self.viewActivityIndicator.backgroundColor = UIColor(red: 255.0/255.0, green: 204.0/255.0, blue: 51.0/255.0, alpha: 0.5)
    self.viewActivityIndicator.layer.cornerRadius = 10

    self.activityIndicator = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
    self.activityIndicator.color = UIColor.blackColor()
    self.activityIndicator.hidesWhenStopped = false

    let titleLabel = UILabel(frame: CGRect(x: 60, y: 0, width: 200, height: 50))
    titleLabel.text = "Processing..."

    self.viewActivityIndicator.addSubview(self.activityIndicator)
    self.viewActivityIndicator.addSubview(titleLabel)

    self.view.addSubview(self.viewActivityIndicator)
}

func doSometing()
{
    self.activityIndicator.startAnimating()
    UIApplication.sharedApplication().beginIgnoringInteractionEvents()

    //do something here that will taking time

    self.activityIndicator.stopAnimating()
    UIApplication.sharedApplication().endIgnoringInteractionEvents()
    self.viewActivityIndicator.removeFromSuperview()
}

2

简单的活动控制器类!

class ActivityIndicator: UIVisualEffectView {


let activityIndictor: UIActivityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.WhiteLarge)
let label: UILabel = UILabel()
let blurEffect = UIBlurEffect(style: .Dark)
let vibrancyView: UIVisualEffectView

init() {

    self.vibrancyView = UIVisualEffectView(effect: UIVibrancyEffect(forBlurEffect: blurEffect))
    super.init(effect: blurEffect)
    self.setup()
}

required init?(coder aDecoder: NSCoder) {

    self.vibrancyView = UIVisualEffectView(effect: UIVibrancyEffect(forBlurEffect: blurEffect))
    super.init(coder: aDecoder)
    self.setup()
}

func setup() {

    contentView.addSubview(vibrancyView)
    vibrancyView.contentView.addSubview(activityIndictor)
    activityIndictor.startAnimating()
}

override func didMoveToSuperview() {
    super.didMoveToSuperview()

    if let superview = self.superview {
        let width: CGFloat = 75.0
        let height: CGFloat = 75.0
        self.frame = CGRectMake(superview.frame.size.width / 2 - width / 2,
                                superview.frame.height / 2 - height / 2,
                                width,
                                height)
        vibrancyView.frame = self.bounds
        let activityIndicatorSize: CGFloat = 40
        activityIndictor.frame = CGRectMake(18, height / 2 - activityIndicatorSize / 2,
                                            activityIndicatorSize,
                                            activityIndicatorSize)
        layer.cornerRadius = 8.0
        layer.masksToBounds = true

    }
}

func show() {
    self.hidden = false
}

func hide() {
    self.hidden = true
}}

用法:-

let activityIndicator = ActivityIndicator()
    self.view.addSubview(activityIndicator)

隐藏 :-

activityIndicator.hide()

2

Xcode 10.1•Swift 4.2

import UIKit

class ProgressHUD: UIVisualEffectView {

    var title: String?
    var theme: UIBlurEffect.Style = .light

    let strLabel = UILabel(frame: CGRect(x: 50, y: 0, width: 160, height: 46))
    let activityIndicator = UIActivityIndicatorView()

    init(title: String, theme: UIBlurEffect.Style = .light) {
        super.init(effect: UIBlurEffect(style: theme))

        self.title = title
        self.theme = theme

        [activityIndicator, strLabel].forEach(contentView.addSubview(_:))
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func didMoveToSuperview() {
        super.didMoveToSuperview()

        if let superview = self.superview {
            frame = CGRect(x: superview.frame.midX - strLabel.frame.width / 2,
                           y: superview.frame.midY - strLabel.frame.height / 2, width: 160, height: 46)

            layer.cornerRadius = 15.0
            layer.masksToBounds = true

            activityIndicator.frame = CGRect(x: 0, y: 0, width: 46, height: 46)
            activityIndicator.startAnimating()

            strLabel.text = title
            strLabel.font = .systemFont(ofSize: 14, weight: UIFont.Weight.medium)

            switch theme {
            case .dark:
                strLabel.textColor = .white
                activityIndicator.style = .white
            default:
                strLabel.textColor = .gray
                activityIndicator.style = .gray
            }
        }

    }

    func show() {
        self.isHidden = false
    }

    func hide() {
        self.isHidden = true
    }
}

使用:

let progress = ProgressHUD(title: "Authorization", theme: .dark)
[progress].forEach(view.addSubview(_:))

2

具有自动宽度和主题支持功能,还可以检测忙碌时的旋转(Swift 3版本)

如下使用它:

var progressView: ProgressView?
override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    self.progressView = ProgressView(message: "Work in progress!",
                                         theme: .dark,
                                         isModal: true)
}

@IBAction func onPause(_ sender: AnyObject) {
    self.progressView.show()      
}

@IBAction func onResume(_ sender: AnyObject) {
    self.progressView.hide()       
}

ProgressView.swift

import UIKit

class ProgressView: UIView {

    enum Theme {
        case light
        case dark
    }

    var theme: Theme
    var container: UIStackView
    var activityIndicator: UIActivityIndicatorView
    var label: UILabel
    var glass: UIView


    private var message: String
    private var isModal: Bool

    init(message: String, theme: theme, isModal: Bool) {
        // Init
        self.message = message
        self.theme = theme
        self.isModal = isModal

        self.container = UIStackView()
        self.activityIndicator = UIActivityIndicatorView()
        self.label = UILabel()
        self.glass = UIView()

        // Get proper width by text message
        let fontName = self.label.font.fontName
        let fontSize = self.label.font.pointSize
        if let font = UIFont(name: fontName, size: fontSize) {
            let fontAttributes = [NSFontAttributeName: font]
            let size = (message as NSString).size(attributes: fontAttributes)
            super.init(frame: CGRect(x: 0, y: 0, width: size.width + 50, height: 50))
        } else {
            super.init(frame: CGRect(x: 0, y: 0, width: 200, height: 50))
        }

        // Detect rotation
        NotificationCenter.default.addObserver(self, selector: #selector(onRotate), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)

        // Style
        self.layer.cornerRadius = 3
        if (self.theme == .dark) {
            self.backgroundColor = .darkGray
        } else {
            self.backgroundColor = .lightGray
        }

        // Label
        if self.theme == .dark {
            self.label.textColor = .white
        }else{
            self.label.textColor = .black
        }
        self.label.text = self.message
        // Container
        self.container.frame = self.frame
        self.container.spacing = 5
        self.container.layoutMargins = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
        self.container.isLayoutMarginsRelativeArrangement = true
        // Activity indicator
        if (self.theme == .dark) {
            self.activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .whiteLarge)
            self.activityIndicator.color = .white
        } else {
            self.activityIndicator = UIActivityIndicatorView(activityIndicatorStyle:.whiteLarge)
            self.activityIndicator.color = .black
        }
        self.activityIndicator.startAnimating()
        // Add them to container

        // First glass
        if let superview = UIApplication.shared.keyWindow {
            if (self.isModal) {
                // glass
                self.glass.frame = superview.frame;
                if (self.theme == .dark) {
                    self.glass.backgroundColor = UIColor.black.withAlphaComponent(0.5)
                } else {
                    self.glass.backgroundColor = UIColor.white.withAlphaComponent(0.5)
                }
                superview.addSubview(glass)
            }
        }
        // Then activity indicator and label
        container.addArrangedSubview(self.activityIndicator)
        container.addArrangedSubview(self.label)
        // Last attach it to container (StackView)
        self.addSubview(container)
        if let superview = UIApplication.shared.keyWindow {
            self.center = superview.center
            superview.addSubview(self)
        }
        //Do not show until show() is called
        self.hide()
    }

    required init(coder: NSCoder) {
        self.theme = .dark
        self.Message = "Not set!"
        self.isModal = true
        self.container = UIStackView()
        self.activityIndicator = UIActivityIndicatorView()
        self.label = UILabel()
        self.glass = UIView()
        super.init(coder: coder)!
    }

    func onRotate() {
        if let superview = self.superview {
            self.glass.frame = superview.frame
            self.center = superview.center
//            superview.addSubview(self)
        }
    }

    public func show() {
        self.glass.isHidden = false
        self.isHidden = false
    }

    public func hide() {
        self.glass.isHidden = true
        self.isHidden = true
    }
}

1

该代码在SWIFT 2.0中有效。

必须声明一个变量以初始化UIActivityIndi​​catorView

let actInd: UIActivityIndicatorView = UIActivityIndicatorView() 

初始化后,将此代码放入控制器中。

actInd.center = ImageView.center
actInd.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.WhiteLarge
view.addSubview(actInd)
actInd.startAnimating()

下载过程完成后,然后隐藏动画。

self.actInd.stopAnimating()

1

在Swift 3中

声明我们将使用的变量

var activityIndicator = UIActivityIndicatorView()
let loadingView = UIView()
let loadingLabel = UILabel()

设置标签,视图和活动指示器

func setLoadingScreen(myMsg : String) {
    let width: CGFloat = 120
    let height: CGFloat = 30
    let x = (self.view.frame.width / 2) - (width / 2)
    let y = (169 / 2) - (height / 2) + 60
    loadingView.frame = CGRect(x: x, y: y, width: width, height: height)
    self.loadingLabel.textColor = UIColor.white
    self.loadingLabel.textAlignment = NSTextAlignment.center
    self.loadingLabel.text = myMsg
    self.loadingLabel.frame = CGRect(x: 0, y: 0, width: 160, height: 30)
    self.loadingLabel.isHidden = false
    self.activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.white
    self.activityIndicator.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
    self.activityIndicator.startAnimating()
    loadingView.addSubview(self.spinner)
    loadingView.addSubview(self.loadingLabel)
    self.view.addSubview(loadingView)
}

开始动画

@IBAction func start_animation(_ sender: Any) {
    setLoadingScreen(myMsg: "Loading...")
}

停止动画

@IBAction func stop_animation(_ sender: Any) {
    self.spinner.stopAnimating()
    UIApplication.shared.endIgnoringInteractionEvents()
    self.loadingLabel.isHidden = true
}

1
import UIKit

class ViewControllerUtils {

    let containerView: UIView = {

        let view = UIView()
        view.translatesAutoresizingMaskIntoConstraints = false
        view.backgroundColor = UIColor(white: 0, alpha: 0.3)
        return view
    }()

    let loadingView: UIView = {

        let view = UIView()
        view.translatesAutoresizingMaskIntoConstraints = false
        view.backgroundColor = UIColor(white: 0, alpha: 0.7)
        view.clipsToBounds = true
        view.layer.cornerRadius = 10
        return view
    }()

    let activityIndicatorView: UIActivityIndicatorView = {

        let aiv = UIActivityIndicatorView()
        aiv.translatesAutoresizingMaskIntoConstraints = false
        aiv.style = UIActivityIndicatorView.Style.whiteLarge
        return aiv
    }()

    let loadingLabel: UILabel = {

        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        label.text = "Loading..."
        label.textAlignment = .center
        label.textColor = .white
        label.font = .systemFont(ofSize: 15, weight: UIFont.Weight.medium)
        return label
    }()

    func showLoader() {

        guard let window = UIApplication.shared.keyWindow else { return }

        window.addSubview(containerView)
        containerView.addSubview(loadingView)
        loadingView.addSubview(activityIndicatorView)
        loadingView.addSubview(loadingLabel)

        containerView.leftAnchor.constraint(equalTo: window.leftAnchor).isActive = true
        containerView.rightAnchor.constraint(equalTo: window.rightAnchor).isActive = true
        containerView.topAnchor.constraint(equalTo: window.topAnchor).isActive = true
        containerView.bottomAnchor.constraint(equalTo: window.bottomAnchor).isActive = true

        loadingView.centerXAnchor.constraint(equalTo: window.centerXAnchor).isActive = true
        loadingView.centerYAnchor.constraint(equalTo: window.centerYAnchor).isActive = true
        loadingView.widthAnchor.constraint(equalToConstant: 120).isActive = true
        loadingView.heightAnchor.constraint(equalToConstant: 120).isActive = true

        activityIndicatorView.centerXAnchor.constraint(equalTo: window.centerXAnchor).isActive = true
        activityIndicatorView.centerYAnchor.constraint(equalTo: window.centerYAnchor).isActive = true
        activityIndicatorView.widthAnchor.constraint(equalToConstant: 60).isActive = true
        activityIndicatorView.heightAnchor.constraint(equalToConstant: 60).isActive = true

        loadingLabel.leftAnchor.constraint(equalTo: loadingView.leftAnchor).isActive = true
        loadingLabel.rightAnchor.constraint(equalTo: loadingView.rightAnchor).isActive = true
        loadingLabel.bottomAnchor.constraint(equalTo: loadingView.bottomAnchor).isActive = true
        loadingLabel.heightAnchor.constraint(equalToConstant: 40).isActive = true

        DispatchQueue.main.async {

            self.activityIndicatorView.startAnimating()
        }
    }

    func hideLoader() {

        DispatchQueue.main.async {

            self.activityIndicatorView.stopAnimating()
            self.activityIndicatorView.removeFromSuperview()
            self.loadingLabel.removeFromSuperview()
            self.loadingView.removeFromSuperview()
            self.containerView.removeFromSuperview()
        }
    }
}

//// In order to show the activity indicator, call the function from your view controller
// let viewControllerUtils = ViewControllerUtils()
// viewControllerUtils.showLoader()

//// In order to hide the activity indicator, call the function from your view controller
// viewControllerUtils.hideLoader()

class ViewControllerUtils2 {

    var container: UIView = UIView()
    var loadingView: UIView = UIView()
    var activityIndicator: UIActivityIndicatorView = UIActivityIndicatorView()
    let loadingLabel = UILabel()

    func showLoader(_ uiView: UIView) {

        container.frame = uiView.frame
        container.center = uiView.center
        container.backgroundColor = UIColor(white: 0, alpha: 0.3)

        loadingView.frame = CGRect(x: 0, y: 0, width: 120, height: 120)
        loadingView.center = uiView.center
        loadingView.backgroundColor = UIColor(white: 0, alpha: 0.7)
        loadingView.clipsToBounds = true
        loadingView.layer.cornerRadius = 10

        activityIndicator.frame = CGRect(x: 0, y: 0, width: 60, height: 60)
        activityIndicator.style = UIActivityIndicatorView.Style.whiteLarge
        activityIndicator.center = CGPoint(x: loadingView.frame.size.width / 2, y: loadingView.frame.size.height / 2)

        loadingLabel.frame = CGRect(x: 0, y: 80, width: 120, height: 40)
        loadingLabel.text = "Loading..."
        loadingLabel.textAlignment = .center
        loadingLabel.textColor = .white
        loadingLabel.font = .systemFont(ofSize: 15, weight: UIFont.Weight.medium)

        uiView.addSubview(container)
        container.addSubview(loadingView)
        loadingView.addSubview(activityIndicator)
        loadingView.addSubview(loadingLabel)

        DispatchQueue.main.async {

            self.activityIndicator.startAnimating()
        }
    }

    func hideLoader() {

        DispatchQueue.main.async {

            self.activityIndicator.stopAnimating()
            self.activityIndicator.removeFromSuperview()
            self.loadingLabel.removeFromSuperview()
            self.loadingView.removeFromSuperview()
            self.container.removeFromSuperview()
        }
    }
}

ViewControllerUtils用于所有视图控制器,与webView一样,请使用ViewControllerUtils2
。.– iAj
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.