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?

dontWatchMyProfile
la source

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];
Vladimir
la source
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é

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

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

Essaye ça:

_imageView.image = image;
[_imageView.layer addAnimation:[CATransition animation] forKey:kCATransition];
Peter Stajger
la source
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
M.Nadeeshan
la source
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()
William Hu
la source
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;
kas-kad
la source
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];
RickiG
la source
2

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

[newView setAlpha:0.0];
[UIView animateWithDuration:0.4 animations:^{
    [newView setAlpha:0.5];
}];
Borut Tomazin
la source
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)
Gurjinder Singh
la source
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
    }
Saleh Enam Shohag
la source