Zmodyfikowałem progressBarDisplayer, aby była klasą i wyświetlam ją, przekazując widok jako parametr. Jak można zidentyfikować progressBarDisplayer, który został już dodany i usunąć go po zakończeniu ładowania?
prostota
1
@simplexity możesz otworzyć nowe pytanie, zamieścić tam swój rzeczywisty kod i dać mi znać, jeśli mam się temu przyjrzeć.
Leo Dabus
Dzięki za twoją odpowiedź! W rzeczywistości skończyło się na przechowywaniu utworzonego widoku w zmiennej i odwoływaniu się do niego removeFromSuperviewi ustawianiu na nil. Nie jestem pewien, czy to najlepszy sposób, ale powyższy kod bardzo pomógł!
prostota
coś dla Objective-C?
Artem Zaytsev
@KrishnaMeena co to nie działa? Jaki jest błąd, który otrzymujesz w której linii?
Leo Dabus
117
Chociaż odpowiedź Esq działa, dodałem własną implementację, która jest bardziej zgodna z dobrą architekturą komponentów, rozdzielając widok na jego własną klasę. Wykorzystuje również dynamiczne rozmycie wprowadzone w iOS 8.
Oto jak wygląda mój z tłem obrazu:
Kod do tego jest zamknięty w swojej własnej klasie UIView, co oznacza, że możesz go ponownie użyć, kiedy tylko chcesz.
Zaktualizowano dla Swift 3
Stosowanie
funcviewDidLoad() {
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
}
Przykład tego, jak go używać, wygląda następująco:
overridefuncviewDidLoad() {
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()
}
Cześć, dziękuję za kod, ale nadal napotykam błędy, deklarując un viewDidLoad zgodnie z sugestią i otrzymuj następujący błąd: 0x2dd698 klasy „_TtC22LabMaternalhaematology11ProgressHUD” nie implementuje doesNotRecognizeSelector: - abort (lldb). Potrzeba, aby móc pokazać i ukryć wewnątrz zamknięć więc potrzeby, aby sprzeciwić się ref ref instancji
dancingbush
@dancingbush, czy kiedykolwiek to rozgryzłeś? Otrzymuję ten sam błąd teraz z jakiegoś powodu nic nie zmienił, błąd właśnie się zaczął
Tyler
1
Jest to zdecydowanie najlepsze podejście (klasa wielokrotnego użytku), ale tekst na etykiecie i pokrętło są zbyt jasne, aby można było je prawidłowo zobaczyć. I label.color = <color>jest ignorowany: -S
Pylinux
1
@ElliottMinns to właśnie miałem na myśli (pseudo kod). Jeśli label.textColor = UIColor.greenColor()to zrobię, nie ma to żadnego wpływu na kolor tekstu.
Pylinux,
2
@ElliottMinns To nie pojawia się na środku ekranu (przetestowano to na symulatorze iPhone 7 Plus)
Dee
19
Oto jak wygląda ten kod:
Oto mój kod przeciągania i upuszczania:
var boxView = UIView()
overridefuncviewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
view.backgroundColor = UIColor.blackColor()
addSavingPhotoView()
//Custom button to test this appvar 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)
}
funcaddSavingPhotoView() {
// 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 initializedvar 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)
}
funcbuttonAction(sender:UIButton!) {
//When button is pressed it removes the boxView from screen
boxView.removeFromSuperview()
}
Szybkie pytanie. Dlaczego wywołujesz funkcję UIApplication.sharedApplication (). BeginIgnoringInteractionEvents () dwukrotnie w doSomething () -> self.activityIndicatorView.startAnimating (), a następnie zaraz po tym wywołaniu?
Jason Foglia
6
Dla Swift 3
Stosowanie
classLoginTVC: UITableViewController{
var loadingView : LoadingView!overridefuncviewDidLoad() {
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@IBActionfuncshowLoadingView(_ sender: UIButton) {
iflet loaderView = loadingView{ // If loadingView already existsif 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@IBActionfunchideLoadingView(_ sender: UIButton) {
iflet loaderView = loadingView{ // If loadingView already exists self.loadingView.hide()
}
}
}
LoadingView Class
classLoadingView{
let uiView : UIViewlet message : Stringlet 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()
}
funcsetup(){
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 dictionarylet 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 loadingViewfuncshow() {
loadingView.isHidden = false
}
// Call this method to show loadingViewfunchide(){
loadingView.isHidden = true
}
// Call this method to check if loading view already existsfuncisHidden() -> Bool{
if loadingView.isHidden == false{
returnfalse
}
else{
returntrue
}
}
}
Twój kod jest łatwy do zrozumienia, ale ja nie działa. Mam przycisk w mojej aplikacji do zapisania obrazu. Właśnie wkleiłem ten kod do IBActionkontrolera w moim widoku i nic się nie stało
rodrigoalvesvieira
Musisz dodać viewjako podwidok widoku, w którym próbujesz pokazać pokrętło. Wygląda też na to, że wersja Apple może używać a UIVisualEffectViewdo rozmycia tła za nią.
Zev Eisenberg
Zobacz komentarz Zeva. Mój kod tworzy widok, ale musisz go gdzieś umieścić. Prawdopodobnie będziesz chciał zrobić coś ładniejszego z wymiarami.
MirekE
Ok, działa tutaj, ale ja to zmieniam wait.hidesWhenStopped = false. Pytanie: jak ukryć przedmiot view?
Thiago Arreguy
Odpowiedź: view.removeFromSuperview ()
Thiago Arreguy
4
Na podstawie odpowiedzi „MirekE” oto kod, który teraz przetestowałem i działa:
Odpowiedzi:
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() } }
źródło
removeFromSuperview
i ustawianiu nanil
. Nie jestem pewien, czy to najlepszy sposób, ale powyższy kod bardzo pomógł!Chociaż odpowiedź Esq działa, dodałem własną implementację, która jest bardziej zgodna z dobrą architekturą komponentów, rozdzielając widok na jego własną klasę. Wykorzystuje również dynamiczne rozmycie wprowadzone w iOS 8.
Oto jak wygląda mój z tłem obrazu:
Kod do tego jest zamknięty w swojej własnej klasie UIView, co oznacza, że możesz go ponownie użyć, kiedy tylko chcesz.
Zaktualizowano dla Swift 3
Stosowanie
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 }
Kod 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 } }
Szybki 2
Przykład tego, jak go używać, wygląda następująco:
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() }
Oto kod 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 } }
Mam nadzieję, że to pomoże. Nie krępuj się używać tego kodu wszędzie tam, gdzie potrzebujesz.
źródło
label.color = <color>
jest ignorowany: -Slabel.textColor = UIColor.greenColor()
to zrobię, nie ma to żadnego wpływu na kolor tekstu.Oto jak wygląda ten kod:
Oto mój kod przeciągania i upuszczania:
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() }
Oto wersja open source tego: https://github.com/goktugyil/CozyLoadingActivity
źródło
Na podstawie mojej poprzedniej odpowiedzi, oto bardziej eleganckie rozwiązanie z niestandardową klasą:
Najpierw zdefiniuj tę klasę niestandardową:
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 }
Teraz w Twojej
UIViewController
klasie: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() }
źródło
Dla Swift 3
Stosowanie
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
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 } } }
źródło
W przypadku wskaźnika aktywności lepiej jest utworzyć jedną klasę niestandardową.
Zamiast tworzyć UIActivityIndicator w każdym UIViewController.Subclass UIView i używać go z dowolnego UIViewController.
Zaktualizowano dla 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() } } }
Umieść tę klasę w swoim projekcie, a następnie wywołaj z dowolnego ViewController jako
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() }
źródło
Możesz stworzyć własne. Na przykład:
Utwórz widok z białym tłem i zaokrąglonymi narożnikami:
var view = UIView(frame: CGRect(x: 0, y: 0, width: 300, height: 50)) view.backgroundColor = UIColor.whiteColor() view.layer.cornerRadius = 10
Dodaj dwa podglądy, a
UIActivityIndicatorView
i aUILabel
: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)
źródło
IBAction
kontrolera w moim widoku i nic się nie stałoview
jako podwidok widoku, w którym próbujesz pokazać pokrętło. Wygląda też na to, że wersja Apple może używać aUIVisualEffectView
do rozmycia tła za nią.wait.hidesWhenStopped = false
. Pytanie: jak ukryć przedmiotview
?Na podstawie odpowiedzi „MirekE” oto kod, który teraz przetestowałem i działa:
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() }
źródło
prosta klasa kontrolera aktywności !!!
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 }}
stosowanie :-
let activityIndicator = ActivityIndicator() self.view.addSubview(activityIndicator)
ukryć :-
źródło
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 } }
Posługiwać się:
let progress = ProgressHUD(title: "Authorization", theme: .dark) [progress].forEach(view.addSubview(_:))
źródło
Dzięki automatycznej szerokości i obsłudze motywów wykrywa również obrót, gdy jest zajęty (wersja Swift 3)
Użyj go jak poniżej:
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 } }
źródło
Ten kod działa w SWIFT 2.0.
Musi zadeklarować zmienną do zainicjowania UIActivityIndicatorView
let actInd: UIActivityIndicatorView = UIActivityIndicatorView()
Po inicjalizacji umieść ten kod w kontrolerze.
actInd.center = ImageView.center actInd.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.WhiteLarge view.addSubview(actInd) actInd.startAnimating()
po zakończeniu procesu pobierania ukryj animację.
self.actInd.stopAnimating()
źródło
W Swift 3
Zadeklaruj zmienne, których będziemy używać
var activityIndicator = UIActivityIndicatorView() let loadingView = UIView() let loadingLabel = UILabel()
Ustaw etykietę, widok i wskaźnik aktywności
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) }
Rozpocznij animację
@IBAction func start_animation(_ sender: Any) { setLoadingScreen(myMsg: "Loading...") }
Zatrzymaj animację
@IBAction func stop_animation(_ sender: Any) { self.spinner.stopAnimating() UIApplication.shared.endIgnoringInteractionEvents() self.loadingLabel.isHidden = true }
źródło
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() } } }
źródło
Dla Swift 5
Wskaźnik z etykietą wewnątrz WKWebview
var strLabel = UILabel() let effectView = UIVisualEffectView(effect: UIBlurEffect(style: .dark)) let loadingTextLabel = UILabel() @IBOutlet var indicator: UIActivityIndicatorView! @IBOutlet var webView: WKWebView! var refController:UIRefreshControl = UIRefreshControl() override func viewDidLoad() { webView = WKWebView(frame: CGRect.zero) webView.navigationDelegate = self webView.uiDelegate = self as? WKUIDelegate let preferences = WKPreferences() preferences.javaScriptEnabled = true let configuration = WKWebViewConfiguration() configuration.preferences = preferences webView.allowsBackForwardNavigationGestures = true webView.load(URLRequest(url: URL(string: "https://www.google.com")!)) setBackground() } func setBackground() { view.addSubview(webView) webView.translatesAutoresizingMaskIntoConstraints = false webView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true webView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true webView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true webView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true } func showActivityIndicator(show: Bool) { if show { strLabel = UILabel(frame: CGRect(x: 55, y: 0, width: 400, height: 66)) strLabel.text = "Please Wait. Checking Internet Connection..." strLabel.font = UIFont(name: "Avenir Light", size: 12) 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: 300, height: 66) effectView.layer.cornerRadius = 15 effectView.layer.masksToBounds = true indicator = UIActivityIndicatorView(style: .white) indicator.frame = CGRect(x: 0, y: 0, width: 66, height: 66) indicator.startAnimating() effectView.contentView.addSubview(indicator) effectView.contentView.addSubview(strLabel) indicator.transform = CGAffineTransform(scaleX: 1.4, y: 1.4); effectView.center = webView.center view.addSubview(effectView) } else { strLabel.removeFromSuperview() effectView.removeFromSuperview() indicator.removeFromSuperview() indicator.stopAnimating() } }
źródło