web-dev-qa-db-fra.com

Indicateur d'activité avec image personnalisée

Je charge une UIWebView et entre-temps, je ne souhaite pas afficher une page vierge avec cettespinner rotation de l'indicateur d'activité (indicateur d'activité siri). D'après ce que j'ai compris, vous ne pouvez pas changer l'image, mais je ne peux pas utiliser cette image et créer une animation avec une rotation de 360 ​​° et une boucle? Ou est-ce que cela videra la batterie? 

quelque chose comme ça?:

- (void)webViewDidStartLoad:(UIWebView *)webView {
    //set up animation        
    [self.view addSubview:self.loadingImage];
    //start animation
}

- (void)webViewDidFinishLoad:(UIWebView *)webView
{   
    //stop animation
    [self.loadingImage removeFromSuperview];
}

Que devrais-je faire?

Merci d'avance!

11
Tibbe

La plupart de cela se trouve dans Stack Overflow. Permettez-moi de résumer:

Créez un UIImageView qui servira d’indicateur d’activité (dans la scène du scénario, du NIB, du code ... où que vous soyez). Appelons-le _activityIndicatorImage

Chargez votre image: _activityIndicatorImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"activity_indicator"]];

Vous devez utiliser une animation pour le faire pivoter. Voici la méthode que j'utilise:

+ (void)rotateLayerInfinite:(CALayer *)layer
{
    CABasicAnimation *rotation;
    rotation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
    rotation.fromValue = [NSNumber numberWithFloat:0];
    rotation.toValue = [NSNumber numberWithFloat:(2 * M_PI)];
    rotation.duration = 0.7f; // Speed
    rotation.repeatCount = HUGE_VALF; // Repeat forever. Can be a finite number.
    [layer removeAllAnimations];
    [layer addAnimation:rotation forKey:@"Spin"];
}

Dans ma méthode layoutSubviews, je lance la rotation. Vous pouvez placer ceci dans votre webViewDidStartLoad et webViewDidFinishLoad si cela convient mieux à votre cas:

- (void)layoutSubviews
{
    [super layoutSubviews];

    // some other code 

    [Utils rotateLayerInfinite:_activityIndicatorImage.layer];
}

Vous pouvez toujours toujours arrêter la rotation en utilisant [_activityIndicatorImage.layer removeAllAnimations];

32
demosten

Vous pouvez utiliser cette belle loader inspirée de Tumblr app:
Asich/AMTumblrHud

4
Almas Adilbek

Swift 4 Sweet Et il suffit de mettre l'extension UIView {}

Réponse modifiée de @gandhi Mena

si vous voulez créer votre propre indicateur de chargement personnalisé

Créez une extension UIView permettant de créer et de personnaliser le logo de votre marque en tant qu’indicateur personnalisé et de placer ce code dans votre fichier de déclaration globale.

extension UIView{
func customActivityIndicator(view: UIView, widthView: CGFloat?,backgroundColor: UIColor?, textColor:UIColor?, message: String?) -> UIView{

    //Config UIView
    self.backgroundColor = backgroundColor //Background color of your view which you want to set

    var selfWidth = view.frame.width
    if widthView != nil{
        selfWidth = widthView ?? selfWidth
    }

    let selfHeigh = view.frame.height
    let loopImages = UIImageView()

    let imageListArray = ["image1", "image2"] // Put your desired array of images in a specific order the way you want to display animation.

    loopImages.animationImages = imageListArray
    loopImages.animationDuration = TimeInterval(0.8)
    loopImages.startAnimating()

    let imageFrameX = (selfWidth / 2) - 30
    let imageFrameY = (selfHeigh / 2) - 60
    var imageWidth = CGFloat(60)
    var imageHeight = CGFloat(60)

    if widthView != nil{
        imageWidth = widthView ?? imageWidth
        imageHeight = widthView ?? imageHeight
    }

    //ConfigureLabel
    let label = UILabel()
    label.textAlignment = .center
    label.textColor = .gray
    label.font = UIFont(name: "SFUIDisplay-Regular", size: 17.0)! // Your Desired UIFont Style and Size
    label.numberOfLines = 0
    label.text = message ?? ""
    label.textColor = textColor ?? UIColor.clear

    //Config frame of label
    let labelFrameX = (selfWidth / 2) - 100
    let labelFrameY = (selfHeigh / 2) - 10
    let labelWidth = CGFloat(200)
    let labelHeight = CGFloat(70)

    // Define UIView frame
    self.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width , height: UIScreen.main.bounds.size.height)


    //ImageFrame
    loopImages.frame = CGRect(x: imageFrameX, y: imageFrameY, width: imageWidth, height: imageHeight)

    //LabelFrame
    label.frame = CGRect(x: labelFrameX, y: labelFrameY, width: labelWidth, height: labelHeight)

    //add loading and label to customView
    self.addSubview(loopImages)
    self.addSubview(label)
    return self }}

Masquer un indicateur, vous pouvez supprimer une sous-vue en haut de la pile de sous-vues. mettez ce code dans le même fichier Swift déclaré globalement.

func hideLoader(removeFrom : UIView){
removeFrom.subviews.last?.removeFromSuperview()
}

Vous pouvez maintenant tirer sur la marque à l'aide de ce code Pour afficher l'indicateur d'activité dans votre contrôleur de vue, saisissez ce code lorsque vous souhaitez afficher.

 self.view.addSubview(UIView().customActivityIndicator(view: self.view, widthView: nil, backgroundColor:"Desired color", textColor: "Desired color", message: "Loading something"))

Pour masquer le chargeur d'animation, vous pouvez utiliser la fonction ci-dessus que vous avez définie globalement. Dans votre ViewController.Swift où vous souhaitez masquer, placez cette ligne de code.

hideLoader(removeFrom: self.view)

imageListArray ressemble à ceci.

 enter image description here

 enter image description here

 enter image description here

2

Sans image, vous pouvez utiliser une bibliothèque tierce 

pour Objective C (également compatible avec iOS 6) https://github.com/shebinkoshy/UIControllsRepo

pour Swift https://github.com/shebinkoshy/Activity-Indicator-Swift

Avantages

-> Capable de définir les couleurs pour spinner

-> Disponible en différentes tailles comme minuscule, petit, moyen, grand, très grand

-> Capable de définir le titre (centre et bas) pour les tailles moyennes, grandes et très grandes

1
Shebin Koshy

Vous pouvez définir un images sur votre activityIndicator. J'ai créé une fonction pour ajouter une image personnalisée à activityIndicator. Voici ce que j'ai créé.

public func showProgressView(view: UIView) -> UIImageView {
    let containerView = UIView()
    let progressView = UIView()
    var activityIndicatorImageView = UIImageView()

    if let statusImage = UIImage(named: Constants.ActivityIndicatorImageName1) {
        let activityImageView = UIImageView(image: statusImage)
        containerView.frame = view.frame
        containerView.backgroundColor = UIColor(hex: 0xffffff, alpha: 0.3)
        progressView.frame = CGRectMake(0, 0, 80, 80)
        progressView.center = CGPointMake(view.bounds.width / 2, view.bounds.height / 2)
        progressView.backgroundColor = UIColor(hex: 0x18bda3, alpha: 0.7)
        progressView.clipsToBounds = true
        progressView.layer.cornerRadius = 10
        activityImageView.animationImages = [UIImage(named: Constants.ActivityIndicatorImageName1)!,
            UIImage(named: Constants.ActivityIndicatorImageName2)!,
            UIImage(named: Constants.ActivityIndicatorImageName3)!,
            UIImage(named: Constants.ActivityIndicatorImageName4)!,
            UIImage(named: Constants.ActivityIndicatorImageName5)!]
        activityImageView.animationDuration = 0.8;
        activityImageView.frame = CGRectMake(view.frame.size.width / 2 - statusImage.size.width / 2, view.frame.size.height / 2 - statusImage.size.height / 2, 40.0, 48.0)
        activityImageView.center = CGPointMake(progressView.bounds.width / 2, progressView.bounds.height / 2)
        dispatch_async(dispatch_get_main_queue()) {
            progressView.addSubview(activityImageView)
            containerView.addSubview(progressView)
            view.addSubview(containerView)
            activityIndicatorImageView = activityImageView
        }
    }
    return activityIndicatorImageView
}

Vous pouvez appeler cette méthode partout dans votre code. Et appelez simplement la méthode startAnimating. Si vous voulez masquer, appelez simplement la méthode stopAnimating.

0
emresancaktar

Vous pouvez créer votre indicateur d'activité personnalisé avec ceci dans Swift 3 & 4 :

Créez un nouveau fichier avec le nom: UIViewExtension.Swift et copiez ce code et collez-le dans votre nouveau fichier:

import UIkit

extension UIView{
   func customActivityIndicator(view: UIView, widthView: CGFloat? = nil,backgroundColor: UIColor? = nil, message: String? = nil,colorMessage:UIColor? = nil ) -> UIView{

    //Config UIView
    self.backgroundColor = backgroundColor ?? UIColor.clear
    self.layer.cornerRadius = 10


    var selfWidth = view.frame.width - 100
    if widthView != nil{
        selfWidth = widthView ?? selfWidth
    }

    let selfHeigh = CGFloat(100)
    let selfFrameX = (view.frame.width / 2) - (selfWidth / 2)
    let selfFrameY = (view.frame.height / 2) - (selfHeigh / 2)
    let loopImages = UIImageView()

    //ConfigCustomLoading with secuence images
    let imageListArray = [UIImage(named:""),UIImage(named:""), UIImage(named:"")]
    loopImages.animationImages = imageListArray
    loopImages.animationDuration = TimeInterval(1.3)
    loopImages.startAnimating()
    let imageFrameX = (selfWidth / 2) - 17
    let imageFrameY = (selfHeigh / 2) - 35
    var imageWidth = CGFloat(35)
    var imageHeight = CGFloat(35)

    if widthView != nil{
        imageWidth = widthView ?? imageWidth
        imageHeight = widthView ?? imageHeight
    }

    //ConfigureLabel
    let label = UILabel()
    label.textAlignment = .center
    label.textColor = .gray
    label.font = UIFont.boldSystemFont(ofSize: 17)
    label.numberOfLines = 0
    label.text = message ?? ""
    label.textColor = colorMessage ?? UIColor.clear

    //Config frame of label
    let labelFrameX = (selfWidth / 2) - 100
    let labelFrameY = (selfHeigh / 2) - 10
    let labelWidth = CGFloat(200)
    let labelHeight = CGFloat(70)

    //add loading and label to customView
    self.addSubview(loopImages)
    self.addSubview(label)

    //Define frames
    //UIViewFrame
    self.frame = CGRect(x: selfFrameX, y: selfFrameY, width: selfWidth , height: selfHeigh)

    //ImageFrame
    loopImages.frame = CGRect(x: imageFrameX, y: imageFrameY, width: imageWidth, height: imageHeight)

    //LabelFrame
    label.frame = CGRect(x: labelFrameX, y: labelFrameY, width: labelWidth, height: labelHeight)

    return self

}

}

Et vous pouvez ensuite l'utiliser dans votre ViewController comme ceci:

import UIKit


class ExampleViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        self.view.addSubview(UIView().customActivityIndicator(view: self.view,backgroundColor: UIColor.green))

    }

   //function for stop and desappear loading
   func deseappearLoading(){
      self.view.subviews.last?.removeFromSuperview()
   }
}

N'oubliez pas de remplacer [UIImage (nommé: ""), UIImage (nommé: ""), UIImage (nommé: "")] par vos noms d'images et réglez TimeInterval (1.3). Profitez-en. 

0
gandhi Mena

cela fonctionne à la fois dans SWIFT 3 et 4

var activityIndicator = UIActivityIndicatorView()
var myView : UIView = UIView()

func viewDidLoad() {
    spinnerCreation()
}

func spinnerCreation() {

    activityIndicator.activityIndicatorViewStyle =  .whiteLarge

    let label = UILabel.init(frame: CGRect(x: 5, y: 60, width: 90, height: 20))
    label.textColor = UIColor.white
    label.font = UIFont.boldSystemFont(ofSize: 14.0)
    label.textAlignment = NSTextAlignment.center
    label.text = "Please wait...."

    myView.frame = CGRect(x: (UIScreen.main.bounds.size.width - 100)/2, y: (UIScreen.main.bounds.size.height - 100)/2, width: 100, height: 100)

    myView.backgroundColor = UIColor.init(white: 0.0, alpha: 0.7)
    myView.layer.cornerRadius = 5
    activityIndicator.center = CGPoint(x: myView.frame.size.width/2, y:  myView.frame.size.height/2 - 10)
    myView.addSubview(activityIndicator)
    myView.addSubview(label)

    myView.isHidden = true
    self.window?.addSubview(myView)
}

@IBAction func activityIndicatorStart(_ sender: Any) {
    myView.isHidden = false
    self.activityIndicator.startAnimating()
    self.view.isUserInteractionEnabled = false
    self.view.bringSubview(toFront: myView)
}

@IBAction func activityIndicatorStop(_ sender: Any)() {
    myView.isHidden = true
    self.activityIndicator.stopAnimating()
    self.view.isUserInteractionEnabled = true
}
0
Sai kumar Reddy

J'ai fait face à un problème similaire ces derniers temps. Et c'est ma solution. En gros, c’est ce que l’initiateur voulait au départ: une page vierge avec un indicateur d’activité personnalisé.
J'ai utilisé partiellement @Azharhussain Shaikh answer mais j'ai implémenté la mise en page automatique au lieu d'utiliser des cadres et ajouté quelques autres améliorations dans le but de rendre l'utilisation aussi simple que possible.

Donc, c'est une extension pour UIView avec deux méthodes: addActivityIndicator () et removeActivityIndicator ()

extension UIView {

func addActivityIndicator() {
    //    creating a view (let's call it "loading" view) which will be added on top of the view you want to have activity indicator on (parent view)
    let view = UIView()
    //    setting up a background for a view so it would make content under it look like not active
    view.backgroundColor = UIColor.white.withAlphaComponent(0.7)

    //    adding "loading" view to a parent view
    //    setting up auto-layout anchors so it would cover whole parent view
    self.addSubview(view)
    view.translatesAutoresizingMaskIntoConstraints = false
    view.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
    view.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
    view.leftAnchor.constraint(equalTo: self.leftAnchor).isActive = true
    view.rightAnchor.constraint(equalTo: self.rightAnchor).isActive = true

    //    creating array with images, which will be animated
    //    in my case I have 30 images with names activity0.png ... activity29.png
    var imagesArray = [UIImage(named: "activity\(0)")!]
    for i in 1..<30 {
        imagesArray.append(UIImage(named: "activity\(i)")!)
    }

    //    creating UIImageView with array of images
    //    setting up animation duration and starting animation
    let activityImage = UIImageView()
    activityImage.animationImages = imagesArray
    activityImage.animationDuration = TimeInterval(0.7)
    activityImage.startAnimating()

    //    adding UIImageView on "loading" view
    //    setting up auto-layout anchors so it would be in center of "loading" view with 30x30 size
    view.addSubview(activityImage)
    activityImage.translatesAutoresizingMaskIntoConstraints = false
    activityImage.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
    activityImage.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
    activityImage.widthAnchor.constraint(equalToConstant: 30).isActive = true
    activityImage.heightAnchor.constraint(equalToConstant: 30).isActive = true
}

func removeActivityIndicator() {
    //    checking if a view has subviews on it
    guard let lastSubView = self.subviews.last else { return }
    //    removing last subview with an assumption that last view is a "loading" view
    lastSubView.removeFromSuperview()
} }

L'effet "Rotation" est obtenu grâce aux 30 images que vous avez insérées dans imagesArray. Chaque image est une nouvelle image d'un indicateur rotatif comme ceci .

Utilisation. Dans votre contrôleur de vue pour afficher un indicateur d'activité, il vous suffit de:

    view.addActivityIndicator()

Pour supprimer un indicateur d'activité:

    view.removeActivityIndicator()

Par exemple, dans le cas de l’utiliser avec la vue tableau (comme je le fais), il peut être utilisé comme ceci:

func setLoadingScreen() {
    view.addActivityIndicator()
    tableView.isScrollEnabled = false
}

func removeLoadingScreen() {
    view.removeActivityIndicator()
    tableView.isScrollEnabled = true
}

Cela fonctionne dans Swift 4.

0
Alex D