How to display an activity indicator with text on iOS 8 with Swift?

前端 未结 14 2156
没有蜡笔的小新
没有蜡笔的小新 2020-11-27 08:58

I wanna show, programmatically, an activity indicator with text, like the one in the Photos app (after editing and saving a picture). How can I do this?

相关标签:
14条回答
  • 2020-11-27 09:37

    You can create your own. For example:

    Create a view with white background and rounded corners:

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

    Add two subviews, a UIActivityIndicatorView and 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)
    
    0 讨论(0)
  • 2020-11-27 09:38

    Based o my previous answer, here is a more elegant solution with a custom class:

    First define this custom class:

    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
    }
    

    Now on your UIViewController class:

    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()
    }
    
    0 讨论(0)
  • 2020-11-27 09:38

    For activity indicator, its better you create one custom class.

    Instead of creating UIActivityIndicator in each UIViewController.Subclass UIView and use from any UIViewController.

    Updated for 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()
    
        }
    }
    }
    

    Put this class in your project and then call from any ViewController as

    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()
    }
    
    0 讨论(0)
  • 2020-11-27 09:40

    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()
        }
    }
    

    0 讨论(0)
  • 2020-11-27 09:44

    simple activity controller class !!!

    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
    }}
    

    usage :-

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

    to hide :-

    activityIndicator.hide()
    
    0 讨论(0)
  • 2020-11-27 09:44

    In Swift 3

    Declare variables which we will use

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

    Set label , view and activityIndicator

    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)
    }
    

    Start Animation

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

    Stop Animation

    @IBAction func stop_animation(_ sender: Any) {
        self.spinner.stopAnimating()
        UIApplication.shared.endIgnoringInteractionEvents()
        self.loadingLabel.isHidden = true
    }
    
    0 讨论(0)
提交回复
热议问题