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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用Swift在iOS 8上显示带有文本的活动指示器?相关的知识,希望对你有一定的参考价值。

我想以编程方式显示带有文本的活动指示器,如照片应用程序中的那个(编辑并保存图片后)。我怎样才能做到这一点?

答案

Xcode 8.2.1•Swift 3.0.2


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: UIFontWeightMedium)
        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.addSubview(activityIndicator)
        effectView.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()
    }
}

sample project

Xcode 9.0•Swift 4.0

    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)
    }
另一答案

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(_:))
另一答案

With auto width and theme support also detects rotate while busy (Swift 3 version)

使用方式如下:

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

以上是关于如何使用Swift在iOS 8上显示带有文本的活动指示器?的主要内容,如果未能解决你的问题,请参考以下文章

iOS 8 上的 UIActivityViewController 显示带有自定义活动的“更多”按钮

Swift 3 iOS 10 - 带有图像和文本的 UICollectionView 无法正确显示

在 UILabel 中显示 HTML 文本,性能问题。 [iPhone SDK、iOS 8、Swift]

在 Swift 中,如何从异步任务外壳内部更新主线程上的文本视图

如何在 iOS 8 中直接启动活动而不显示共享表?

SWIFT iOS - 从多行 uitextview 获取带有换行符的文本,因为它们在屏幕上可见