Come animare il cambiamento di immagine in un UIImageView?


199

Ho un UIImageViewcon un'immagine. Ora ho un'immagine completamente nuova (file grafico) e voglio visualizzarla in questo UIImageView. Se ho appena impostato

myImageView.image = newImage;

la nuova immagine è immediatamente visibile. Non animabile.

Voglio che si dissolva bene nella nuova immagine. Pensavo che forse ci fosse una soluzione migliore che crearne una nuova UIImageViewe fondersi con l'animazione?


Risposte:


260

Non sono sicuro che sia possibile animare le UIVview con effetto dissolvenza in quanto sembra che tutte le transizioni delle viste supportate siano definite UIViewAnimationTransitionnell'enumerazione. L'effetto di dissolvenza può essere ottenuto utilizzando CoreAnimation. Esempio di esempio per questo approccio:

#import <QuartzCore/QuartzCore.h>
...
imageView.image = [UIImage imageNamed:(i % 2) ? @"3.jpg" : @"4.jpg"];

CATransition *transition = [CATransition animation];
transition.duration = 1.0f;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionFade;

[imageView.layer addAnimation:transition forKey:nil];

2
Il tuo codice ha funzionato perfettamente quando si passa da un'immagine all'altra. Sai come farlo funzionare con l'animazione automatica delle immagini in UIImageView (proprietà animationImages)?
CedricSoubrie,

Puoi provare a usare CAKeyFrameAnimation per la proprietà content del layer, non sono sicuro se l'effetto sarà lo stesso. Oppure imposta il delegato animazione e nella funzione di callback delegato inizia l'animazione all'immagine successiva al termine dell'animazione precedente.
Vladimir,

2
Questo è decisamente più semplice rispetto alla dissolvenza manuale incrociata di una vista immagine separata. Grazie!
Kevlar,

Bene .. Se la cornice delle visualizzazioni delle immagini cambia, rimane nella stessa posizione .. è un grosso problema!
hfossli,

@Fossli, vuoi dire quando il frame cambia durante l'animazione? Questa è una domanda diversa
Vladimir,

368
[UIView transitionWithView:textFieldimageView
                  duration:0.2f
                   options:UIViewAnimationOptionTransitionCrossDissolve
                animations:^{
                    imageView.image = newImage;
                } completion:nil];

è un'altra possibilità


1
semplice e apre un'intera gamma di altri effetti di animazione tra le immagini.
So Over It,

1
Ha lo stesso problema menzionato da @hfossli in merito ai cambi di frame. L'animazione sarebbe lenta se i layout cambiassero durante quello.
Geva,

1
Questa è la soluzione migliore, perché può essere combinata con altre animazioni.
Kelin,

161

Nelle parole di Michael Scott, mantienilo semplicemente stupido. Ecco un modo semplice per farlo in Swift 3 e Swift 4 :

UIView.transition(with: imageView,
                  duration: 0.75,
                  options: .transitionCrossDissolve,
                  animations: { self.imageView.image = toImage },
                  completion: nil)

3
Funziona come un fascino. Grazie!
Roberto Allende,

1
Ottimo Uau! Non lo sapevo da così tanto tempo :)
sabiland

1
Questo cambierà in 1 immagine. cosa succede se ho una serie di immagini e voglio mostrare una per una con l'animazione di transizione?
Ammar Mujeeb,

1
È possibile utilizzare il blocco di completamento per passare al successivo.
Zia

41

Ecco un esempio in Swift che prima dissolverà una nuova immagine e poi aggiungerà un'animazione rimbalzante:

var selected: Bool {
  willSet(selected) {
    let expandTransform:CGAffineTransform = CGAffineTransformMakeScale(1.15, 1.15);
    if (!self.selected && selected) {
      UIView.transitionWithView(self.imageView,
        duration:0.1,
        options: UIViewAnimationOptions.TransitionCrossDissolve,
        animations: {
          self.imageView.image = SNStockCellSelectionAccessoryViewImage(selected)
          self.imageView.transform = expandTransform
        },
        completion: {(finished: Bool) in
          UIView.animateWithDuration(0.4,
            delay:0.0,
            usingSpringWithDamping:0.40,
            initialSpringVelocity:0.2,
            options:UIViewAnimationOptions.CurveEaseOut,
            animations: {
              self.imageView.transform = CGAffineTransformInvert(expandTransform)
            }, completion:nil)
      })
    }
  }
}

var imageView:UIImageView

Se imageViewviene aggiunto correttamente alla vista come vista secondaria, alternare tra selected = falseto selected = truedovrebbe scambiare l'immagine con un'animazione rimbalzante. SNStockCellSelectionAccessoryViewImagerestituisce solo un'immagine diversa in base allo stato di selezione corrente, vedere di seguito:

private let SNStockCellSelectionAccessoryViewPlusIconSelected:UIImage = UIImage(named:"PlusIconSelected")!
private let SNStockCellSelectionAccessoryViewPlusIcon:UIImage = UIImage(named:"PlusIcon")!

private func SNStockCellSelectionAccessoryViewImage(selected:Bool) -> UIImage {
  return selected ? SNStockCellSelectionAccessoryViewPlusIconSelected : SNStockCellSelectionAccessoryViewPlusIcon
}

L'esempio GIF qui sotto è un po 'rallentato, l'animazione effettiva avviene più velocemente:

                                       UIImageView rimbalza animazione Gif


16

Codice:

var fadeAnim:CABasicAnimation = CABasicAnimation(keyPath: "contents");

fadeAnim.fromValue = firstImage;
fadeAnim.toValue   = secondImage;
fadeAnim.duration  = 0.8;         //smoothest value

imageView.layer.addAnimation(fadeAnim, forKey: "contents");

imageView.image = secondImage;

Esempio:

UIImageView Esempio dal codice

Soluzione divertente e più dettagliata : ( Attivare un tocco )

    let fadeAnim:CABasicAnimation = CABasicAnimation(keyPath: "contents");

    switch imageView.image {
        case firstImage?:
            fadeAnim.fromValue = firstImage;
            fadeAnim.toValue   = secondImage;
            imageView.image    = secondImage;
        default:
            fadeAnim.fromValue = secondImage;
            fadeAnim.toValue   = firstImage;
            imageView.image    = firstImage;
    }

    fadeAnim.duration = 0.8;

    imageView.layer.addAnimation(fadeAnim, forKey: "contents");

10

Prova questo:

_imageView.image = image;
[_imageView.layer addAnimation:[CATransition animation] forKey:kCATransition];

swift: _imageView.layer.addAnimation (CATransition (), forKey: kCATransition)
Eugene Braginets

8

Con Swift 3

extension UIImageView{   
 var imageWithFade:UIImage?{
        get{
            return self.image
        }
        set{
            UIView.transition(with: self,
                              duration: 0.5, options: .transitionCrossDissolve, animations: {
                                self.image = newValue
            }, completion: nil)
        }
    }
}

Uso:

myImageView.imageWithFade = myImage

6

Perché non provarlo.

NSArray *animationFrames = [NSArray arrayWithObjects:
  [UIImage imageWithName:@"image1.png"],
  [UIImage imageWithName:@"image2.png"], 
  nil];

UIImageView *animatedImageView = [[UIImageView alloc] init];
animatedImageView.animationImages = animationsFrame;
[animatedImageView setAnimationRepeatCount:1];
[animatedImageView startAnimating];

Una versione rapida:

let animationsFrames = [UIImage(named: "image1.png"), UIImage(named: "image2.png")]
let animatedImageView = UIImageView()
animatedImageView.animationImages = animationsFrames
animatedImageView.animationRepeatCount = 1
animatedImageView.startAnimating()

Questo imposta UIImageView in modo che si ripeta per sempre ... l'autore stava solo chiedendo una modifica :(
J-Dizzle,

setAnimationRepeatCount
William Hu,

SetAnimationRepeatCount non cambia nulla. Non si ferma mai
Yucel Bayram,

5
CABasicAnimation* fadeAnim = [CABasicAnimation animationWithKeyPath:@"contents"];
fadeAnim.fromValue = (__bridge id)imageView.image.CGImage;
fadeAnim.toValue = (__bridge id)[UIImage imageNamed:@"newImage.png"].CGImage;
fadeAnim.duration = 2.0;
[imageView.layer addAnimation:fadeAnim forKey:@"contents"];
imageView.layer.contents = (__bridge id)[UIImage imageNamed:@"newImage.png"].CGImage;

3

Ci sono alcuni approcci diversi qui: UIAnimazioni al mio ricordo sembra la tua sfida.

Modifica: troppo pigro di me :)

Nel post, mi riferivo a questo metodo:

[newView setFrame:CGRectMake( 0.0f, 480.0f, 320.0f, 480.0f)]; //notice this is OFF screen!
[UIView beginAnimations:@"animateTableView" context:nil];
[UIView setAnimationDuration:0.4];
[newView setFrame:CGRectMake( 0.0f, 0.0f, 320.0f, 480.0f)]; //notice this is ON screen!
[UIView commitAnimations];

Ma invece di animare il fotogramma, animi l'alfa:

[newView setAlpha:0.0]; // set it to zero so it is all gone.
[UIView beginAnimations:@"animateTableView" context:nil];
[UIView setAnimationDuration:0.4];
[newView setAlpha:0.5]; //this will change the newView alpha from its previous zero value to 0.5f
[UIView commitAnimations];

2

A partire da iOS 5 questo è molto più semplice:

[newView setAlpha:0.0];
[UIView animateWithDuration:0.4 animations:^{
    [newView setAlpha:0.5];
}];

4
Ciò non aiuta il problema originale, ovvero che hai già un'immagine visualizzata e vuoi dissolvenza incrociata su una nuova immagine ...
Kendall Helmstetter Gelner

4
giusto .. questa risposta non risolve la domanda. La domanda non era come svanire nella visualizzazione immagine ma come sfumare da una vecchia immagine a una nuova immagine. I blocchi di animazione sono stati introdotti in iOS 4.
Bastian,

2

Swift 4 Questo è semplicemente fantastico

  self.imgViewPreview.transform = CGAffineTransform(scaleX: 0, y: 0)
          UIView.animate(withDuration: 1, delay: 0, usingSpringWithDamping: 0.3, initialSpringVelocity: 0, options: .curveEaseOut, animations: {
              self.imgViewPreview.image = newImage
              self.imgViewPreview.transform = .identity
          }, completion: nil)

1

La risposta di Vladimir è perfetta, ma chiunque come me è alla ricerca di una soluzione rapida

Questa soluzione funziona per la rapida versione 4.2

var i = 0
    func animation(){
        let name = (i % 2 == 0) ? "1.png" : "2.png"
        myImageView.image = UIImage.init(named: name)
        let transition: CATransition = CATransition.init()
        transition.duration = 1.0
        transition.timingFunction = CAMediaTimingFunction.init(name: .easeInEaseOut)
        transition.type = .fade
        myImageView.layer.add(transition, forKey: nil)
        i += 1
    }

Puoi chiamare questo metodo da qualsiasi luogo. Cambia l'immagine alla successiva (immagine) con l'animazione.

Per Swift Versione 4.0 Utilizzare la seguente soluzione

var i = 0
    func animationVersion4(){
        let name = (i % 2 == 0) ? "1.png" : "2.png"
        uiImage.image = UIImage.init(named: name)
        let transition: CATransition = CATransition.init()
        transition.duration = 1.0
        transition.timingFunction = CAMediaTimingFunction.init(name: kCAMediaTimingFunctionEaseInEaseOut)
        transition.type = kCATransitionFade
        uiImage.layer.add(transition, forKey: nil)
        i += 1
    }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.