web-dev-qa-db-de.com

Laden eines "Overlays" beim Ausführen langer Aufgaben in iOS

Was ist ein Beispiel für das Laden von Overlays in Swift IOS Anwendung bei langen Aufgaben. Beispiel für das Laden von Daten vom Remote-Server. Ich habe gegoogelt, aber keine Antwort gefunden.

Aktualisiert:

Danke für @Sebastian Dressler, das ist ganz einfach. Ich habe meinen Code aktualisiert und es läuft cool

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

lassen mit:

LoadingOverlay.shared.showOverlay(self.view)
//To to long tasks
LoadingOverlay.shared.hideOverlayView()
60
Sonrobby

Die obigen Antworten fügen eine Ladeansicht hinzu, blockieren jedoch keine Klickereignisse auf dem Bildschirm und bieten keine Überlagerung für den Rest des Bildschirms. Sie können es wie folgt erreichen:

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 und neuer

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)

und Sie können es wie folgt ausblenden:

dismiss(animated: false, completion: nil)

Es wird wie folgt gezeigt: enter image description here

153
Ajinkya Patil

Erstellen Sie einfach eine Überlagerungsansicht, die Sie zu Ihrer übergeordneten Ansicht hinzufügen, und entfernen Sie sie, wenn Ihre Aufgabe erledigt ist, z. um es hinzuzufügen:

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

Zum Entfernen:

overlay?.removeFromSuperview()
32

Hintergrundunschärfe + Aktivitätsanzeige, Swift 5 Beispiel

extension UIView {
    func showBlurLoader() {
        let blurLoader = BlurLoader(frame: frame)
        self.addSubview(blurLoader)
    }

    func removeBluerLoader() {
        if let blurLoader = subviews.first(where: { $0 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()
    }
}

demo

22
Maor

Für jemanden wie mich habe ich einige Änderungen am @ Sonrobby-Code vorgenommen. Nach meinem Verständnis fügt @Sonrobby die Aktivität bei jedem showOverlay -Aufruf zum Overlay hinzu. Ein Teil der Konfiguration kann an die init-Funktion übergeben werden, sodass nur die Platzierung in der showOverlay -Methode zulässig ist.

Ich ändere auch den Hintergrund der Überlagerung in Schwarz, da meine App überwiegend weiß ist.

hier ist der Code:

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

Wenn Sie versuchen, den Code manchmal auszuführen, können Probleme auftreten, um die angegebenen Antworten zu ergänzen. Persönlich gab es eine Gelegenheit, in der showOverlay nicht richtig aufgerufen wurde (weil ich versuchte, in eine Szene zu springen und diese Funktion dann sofort während viewDidLoad aufzurufen).

Wenn Sie auf ein ähnliches Problem stoßen wie ich, gibt es eine Korrektur des Codes und eine Änderung der Vorgehensweise, die ich empfehle.

UPDATE: Platzieren Sie beide Codeblöcke wie folgt als Abschlüsse für einen dispatch_async-Aufruf:

dispatch_async(dispatch_get_main_queue(),
 { //code });

Vorgehensweise: Wenn Sie Ihren Code aufrufen, führen Sie einen dispatch_after-Aufruf in der Hauptwarteschlange aus, um den Anruf um einige Millisekunden zu verzögern.

Die Begründung? Sie bitten die Benutzeroberfläche lediglich, während viewDidLoad zu viel zu tun.

Wenn dieser Anhang zur Lösung geholfen hat, würde ich mich freuen.

-Joel Long

P.S. Die Lösung funktionierte für XCode v6.3.2

5
Joel Long

@Sonrobby answer aktualisiert, Hintergrundansicht und Orientierungshilfe über die Größenänderungsmaske hinzugefügt ... dies kann für einfache Dinge verwendet werden

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

wenn Sie es zu keywindow hinzufügen, kann es auch über die Navigations- und Tab-Leisten gehen ... in etwa so

LoadingOverlay.shared.showOverlay(view: UIApplication.shared.keyWindow!)
4
anoop4real

Verwenden Sie ATKit.

Siehe: https://aurvan.github.io/atkit-ios-release/index.html

ATProgressOverlay-Klasse https://aurvan.github.io/atkit-ios-release/helpbook/Classes/ATProgressOverlay.html

Code:

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.

Bildschirmfoto:

Loading OverlayScreenshot

3
Rupendra

Ich habe ein Protokoll erstellt, um Ihren eigenen View Controller als Overlay darzustellen. Die Verwendung ist sehr einfach:

class ViewController: UIViewController, OverlayHost {
    @IBAction func showOverlayButtonPressed() {
        showOverlay(type: YourOverlayViewController.self, 
            fromStoryboardWithName: "Main")
    }
}

Ergebnis:

Swift OverlayViewController

Quellcode: https://github.com/agordeev/OverlayViewController

Passender Artikel: https://andreygordeev.com/2017/04/18/overlay-view-controller-protocols-Swift/

2
Andrey Gordeev

Schnell 3.

Ich habe @ Luchos Code in seiner Antwort unten verwendet und die Hintergrundfarbe der Überlagerung geändert, um sie zu löschen und eine Spinnerfarbe hinzuzufügen.

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