¿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.

dontWatchMyProfile
fuente

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];
Vladimir
fuente
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

Ilker Baltaci
fuente
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)
Zia
fuente
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

Zorayr
fuente
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");
J-Dizzle
fuente
10

Prueba esto:

_imageView.image = image;
[_imageView.layer addAnimation:[CATransition animation] forKey:kCATransition];
Peter Stajger
fuente
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
M. Nadeeshan
fuente
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()
William Hu
fuente
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;
kas-kad
fuente
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];
RickiG
fuente
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];
}];
Borut Tomazin
fuente
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)
Gurjinder Singh
fuente
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
    }
Saleh Enam Shohag
fuente