Comment animer le changement d'image dans un UIImageView?


199

J'ai un UIImageViewavec une image. Maintenant, j'ai une toute nouvelle image (fichier graphique) et je veux l'afficher ici UIImageView. Si je viens de mettre

myImageView.image = newImage;

la nouvelle image est immédiatement visible. Pas animable.

Je veux qu'elle se fane bien dans la nouvelle image. Je pensais qu'il y avait peut-être une meilleure solution que de simplement en créer un nouveau UIImageViewet de le mélanger avec l'animation?


Réponses:


260

Je ne sais pas si vous pouvez animer des UIViews avec un effet de fondu car il semble que toutes les transitions de vue prises en charge soient définies dans l' UIViewAnimationTransitionénumération. L'effet de décoloration peut être obtenu en utilisant CoreAnimation. Exemple d'exemple pour cette approche:

#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
Votre code fonctionnait parfaitement lors du passage d'une image à une autre. Savez-vous comment le faire fonctionner avec une animation automatique d'images dans un UIImageView (propriété animationImages)?
CedricSoubrie

Vous pouvez essayer d'utiliser CAKeyFrameAnimation pour la propriété de contenu de la couche, mais vous ne savez pas si l'effet sera le même. Ou définissez le délégué d'animation et dans la fonction de rappel de délégué commencez l'animation à l'image suivante lorsque l'animation précédente se termine.
Vladimir

2
C'est certainement plus simple que de fondre manuellement une vue d'image séparée. Merci!
Kevlar

Eh bien .. Si le cadre des images vues change alors il reste dans sa même position .. c'est une affaire de rupture!
hfossli

@Fossli, tu veux dire quand l'image change pendant l'animation? C'est une question différente alors
Vladimir

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

est une autre possibilité


1
simple et ouvre toute une gamme d'autres effets d'animation entre les images.
So Over It

1
A le même problème que @hfossli a mentionné concernant les changements de trame. L'animation serait lente si les dispositions sont modifiées pendant cette période.
Geva

1
C'est la meilleure solution, car elle peut être combinée avec d'autres animations.
kelin

161

Pour reprendre les mots de Michael Scott, restez simple et stupide. Voici un moyen simple de le faire dans Swift 3 et Swift 4 :

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

3
Fonctionne comme un charme. Merci!
RobertoAllende du

1
Uau génial! Je ne savais pas à ce sujet si longtemps :)
sabiland

1
Cela changera en 1 image. que se passe-t-il si j'ai un tableau d'images et que je souhaite afficher une à une avec une animation de transition?
Ammar Mujeeb

1
Vous pouvez utiliser le bloc d'achèvement pour passer au suivant.
Zia

41

Voici un exemple dans Swift qui va d'abord dissoudre une nouvelle image, puis ajouter une animation rebondissante:

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 imageViewest correctement ajouté à la vue en tant que sous-vue, le basculement entre selected = falseto selected = truedoit permuter l'image avec une animation rebondissante. SNStockCellSelectionAccessoryViewImagerenvoie simplement une image différente en fonction de l'état de sélection actuel, voir ci-dessous:

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'exemple GIF ci-dessous est un peu ralenti, l'animation réelle se produit plus rapidement:

                                       UIImageView animation de rebond Gif


16

Code:

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;

Exemple:

Exemple UIImageView du code

Solution amusante et plus verbeuse : ( Basculer sur un robinet )

    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

Essaye ça:

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

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

8

Avec 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)
        }
    }
}

Usage:

myImageView.imageWithFade = myImage

6

Pourquoi ne pas essayer ça.

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

Une version rapide:

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

Cela définit l'UIImageView pour répéter le basculement pour toujours ... l'auteur demandait juste un changement cependant :(
J-Dizzle

setAnimationRepeatCount
William Hu

SetAnimationRepeatCount ne change rien. Ça ne s'arrête jamais
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

Il y a quelques approches différentes ici: UIAnimations à mon souvenir cela ressemble à votre défi.

Edit: trop paresseux de moi :)

Dans le post, je faisais référence à cette méthode:

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

Mais au lieu d'animer le cadre, vous animez l'alpha:

[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

Depuis iOS 5, celui-ci est beaucoup plus simple:

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

4
Cela n'aide pas le problème d'origine, à savoir que vous avez déjà une image affichée et que vous souhaitez effectuer un fondu enchaîné vers une nouvelle image ...
Kendall Helmstetter Gelner

4
à droite .. cette réponse ne résout pas la question. La question n'était pas de savoir comment fondre dans la vue d'image, mais de passer d'une ancienne image à une nouvelle image. Les blocs d'animation ont été introduits dans iOS 4.
Bastian le

2

Swift 4 C'est tout simplement génial

  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 réponse de Vladimir est parfaite, mais toute personne comme moi qui cherche une solution rapide

Cette solution est travaillée pour swift version 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
    }

Vous pouvez appeler cette méthode de n'importe où. Il changera l'image à la suivante (image) avec animation.

Pour Swift version 4.0 Utilisez la solution ci-dessous

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
    }
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.