¿Cómo animar el cambio de imagen en un UIImageView?


199

Tengo un UIImageViewcon una imagen. Ahora tengo una imagen completamente nueva (archivo gráfico), y quiero mostrar eso en esto UIImageView. Si solo establezco

myImageView.image = newImage;

La nueva imagen es visible de inmediato. No es animable

Quiero que se desvanezca agradablemente en la nueva imagen. Pensé que tal vez hay una mejor solución que simplemente crear una nueva UIImageViewademás de combinarla con la animación.


Respuestas:


260

No estoy seguro de si puede animar UIViews con efecto de desvanecimiento, ya que parece que todas las transiciones de vista compatibles se definen en la UIViewAnimationTransitionenumeración. El efecto de desvanecimiento se puede lograr con CoreAnimation. Ejemplo de ejemplo para este enfoque:

#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
Su código funcionó perfectamente al pasar de una imagen a otra. ¿Sabes cómo hacer que funcione con animación automática de imágenes en un UIImageView (propiedad de animationImages)?
CedricSoubrie

Puede intentar usar CAKeyFrameAnimation para la propiedad de contenido de la capa, aunque no estoy seguro de si el efecto será el mismo. O configure delegado de animación y en la función de devolución de llamada delegada comience a animar a la siguiente imagen cuando finalice la animación anterior.
Vladimir

2
Esto es definitivamente más simple que fundir manualmente una vista de imagen separada. ¡Gracias!
Kevlar

Bueno ... Si el marco de vistas de imagen cambia, entonces permanece en su misma posición ... ¡eso es un factor decisivo!
hfossli

@ Fossli, ¿quieres decir cuando el marco cambia durante la animación? Esa es una pregunta diferente entonces
Vladimir

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

es otra posibilidad


1
simple y abre una gama completa de otros efectos de animación entre las imágenes.
So Over It

1
Tiene el mismo problema que @hfossli mencionó con respecto a los cambios de marco. La animación sería lenta si los diseños se cambian durante eso.
Geva

1
Esta es la mejor solución, ya que se puede combinar con otras animaciones.
Kelin

161

En palabras de Michael Scott, que sea simple estúpido. Aquí hay una manera simple de hacer esto en Swift 3 y Swift 4 :

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

3
Funciona de maravilla. ¡Gracias!
RobertoAllende

1
Uau genial! No sabía sobre esto maldita sea por tanto tiempo :)
sabiland

1
Esto cambiará a 1 imagen. ¿Qué pasa si tengo una variedad de imágenes y quiero mostrar una por una con animación de transición?
Ammar Mujeeb

1
Puede usar el bloque de finalización para pasar al siguiente.
Zia

41

Aquí hay un ejemplo en Swift que primero disolverá una nueva imagen y luego agregará una animación animada:

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

Si imageViewse agrega correctamente a la vista como una subvista, alternar entre selected = falsepara selected = truecambiar la imagen con una animación animada. SNStockCellSelectionAccessoryViewImagesolo devuelve una imagen diferente en función del estado de selección actual, consulte a continuación:

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

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

El ejemplo GIF a continuación se ralentiza un poco, la animación real ocurre más rápido:

                                       UIImageView rebote animación GIF


16

Código:

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;

Ejemplo:

UIImageView Ejemplo del código

Solución divertida y más detallada : ( alternar con un toque )

    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

Prueba esto:

_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

¿Por qué no probar esto?

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 versión rápida:

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

Esto configura el UIImageView para que se repita para siempre ... sin embargo, el autor solo estaba pidiendo un cambio :(
J-Dizzle

setAnimationRepeatCount
William Hu

SetAnimationRepeatCount no cambia nada. Nunca se detiene
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

Aquí hay algunos enfoques diferentes: UIAnimaciones para mi recuerdo, suena como su desafío.

Editar: demasiado flojo de mi parte :)

En la publicación, me refería a este método:

[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];

Pero en lugar de animar el marco, animas el 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 partir de iOS 5, este es mucho más fácil:

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

44
Eso no resuelve el problema original, que es que ya tiene una imagen mostrada y desea
fundirse

44
correcto ... esta respuesta no resuelve la pregunta. La pregunta no era cómo desvanecerse en la vista de imagen, sino desvanecerse de una imagen antigua a una nueva. Los bloques de animación se introdujeron en iOS 4.
Bastian

2

Swift 4 Esto es simplemente increíble

  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 respuesta de Vladimir es perfecta, pero cualquiera como yo que busca una solución rápida

Esta solución se trabajó para la versión rápida de 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
    }

Puede llamar a este método desde cualquier lugar. Cambiará la imagen a la siguiente (imagen) con animación.

Para la versión 4.0 de Swift, utilice la siguiente solución

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
    }
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.