Plutôt que d'en créer deux UIImageViews
, il semble logique de simplement changer la image
vue d'une vue. Si je fais cela, y a-t-il de toute façon un fondu / fondu croisé entre les deux images plutôt qu'un commutateur instantané?
Plutôt que d'en créer deux UIImageViews
, il semble logique de simplement changer la image
vue d'une vue. Si je fais cela, y a-t-il de toute façon un fondu / fondu croisé entre les deux images plutôt qu'un commutateur instantané?
Réponses:
Edit: il y a une meilleure solution de @algal ci-dessous .
Une autre façon de procéder consiste à utiliser des transitions CAAnimation prédéfinies:
CATransition *transition = [CATransition animation];
transition.duration = 0.25;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionFade;
transition.delegate = self;
[self.view.layer addAnimation:transition forKey:nil];
view1.hidden = YES;
view2.hidden = NO;
Consultez l'exemple de projet View Transitions d'Apple: https://developer.apple.com/library/content/samplecode/ViewTransitions/Introduction/Intro.html#//apple_ref/doc/uid/DTS40007411
Cela peut être beaucoup plus simple en utilisant les nouvelles UIKit animation
méthodes basées sur des blocs .
Supposons que le code suivant se trouve dans le contrôleur de vue et que l'UIImageView que vous souhaitez dissoudre de manière croisée soit une sous-vue de self.view adressable via la propriété.Tout self.imageView
ce dont vous avez besoin est:
UIImage * toImage = [UIImage imageNamed:@"myname.png"];
[UIView transitionWithView:self.imageView
duration:5.0f
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
self.imageView.image = toImage;
} completion:nil]
Terminé.
Et pour le faire dans Swift, c'est comme ça:
let toImage = UIImage(named:"myname.png")
UIView.transitionWithView(self.imageView,
duration:5,
options: UIViewAnimationOptions.TransitionCrossDissolve,
animations: { self.imageView.image = toImage },
completion: nil)
Swift 3, 4 et 5
let toImage = UIImage(named:"myname.png")
UIView.transition(with: self.imageView,
duration: 0.3,
options: .transitionCrossDissolve,
animations: {
self.imageView.image = toImage
},
completion: nil)
Pour Swift 3.0.1:
UIView.transition(with: self.imageView,
duration:0.5,
options: .transitionCrossDissolve,
animations: { self.imageView.image = newImage },
completion: nil)
Référence: https://gist.github.com/licvido/bc22343cacfa3a8ccf88
Oui, ce que vous dites est absolument correct et c'est la façon de le faire. J'ai écrit cette méthode et je l'utilise toujours pour fondre mon image. Je m'occupe CALayer
de ça. Vous devez importer Core Animation pour cela.
+ (void)fadeInLayer:(CALayer *)l
{
CABasicAnimation *fadeInAnimate = [CABasicAnimation animationWithKeyPath:@"opacity"];
fadeInAnimate.duration = 0.5;
fadeInAnimate.repeatCount = 1;
fadeInAnimate.autoreverses = NO;
fadeInAnimate.fromValue = [NSNumber numberWithFloat:0.0];
fadeInAnimate.toValue = [NSNumber numberWithFloat:1.0];
fadeInAnimate.removedOnCompletion = YES;
[l addAnimation:fadeInAnimate forKey:@"animateOpacity"];
return;
}
Vous pouvez faire le contraire pour Fade out une image. Après qu'il s'estompe. Vous venez de le supprimer de superview (ce qui est UIImageView
). [imageView removeFromSuperview]
.
Vous pouvez également empaqueter la fonctionnalité de fondu d'entrée dans une sous-classe, de sorte que vous puissiez ensuite l'utiliser comme une UIImageView commune, comme dans l'exemple suivant:
IMMFadeImageView *fiv=[[IMMFadeImageView alloc] initWithFrame:CGRectMake(10, 10, 50, 50)];
[self.view addSubview:fiv];
fiv.image=[UIImage imageNamed:@"initialImage.png"];
fiv.image=[UIImage imageNamed:@"fadeinImage.png"]; // fades in
Une implémentation possible suit.
Remarque: la façon dont vous implémentez réellement le fondu d'entrée dans la setImage:
fonction peut changer et pourrait être l'un des autres excellents exemples décrits dans les autres réponses à cette question - créer un autre à la volée UIImageView
comme je le fais ici pourrait être une surcharge inacceptable dans votre situation spécifique .
IMMFadeImageView.h :
#import <UIKit/UIKit.h>
@interface IMMFadeImageView : UIImageView
@property (nonatomic,assign) float fadeDuration;
@end
IMMFadeImageView.m :
#import "IMMFadeImageView.h"
@implementation IMMFadeImageView
@synthesize fadeDuration;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.fadeDuration=1;
}
return self;
}
-(void)setImage:(UIImage *)newImage{
if(!self.image||self.fadeDuration<=0){
super.image=newImage;
} else {
UIImageView *iv=[[UIImageView alloc] initWithFrame:self.bounds];
iv.contentMode=self.contentMode;
iv.image=super.image;
iv.alpha=1;
[self addSubview:iv];
super.image=newImage;
[UIView animateWithDuration:self.fadeDuration delay:0 options:UIViewAnimationCurveEaseInOut animations:^{
iv.alpha=0;
} completion:^(BOOL finished) {
[iv removeFromSuperview];
}];
}
}
Le code ci-dessus repose sur quelques hypothèses (y compris l'activation d'ARC dans votre projet XCode), est uniquement destiné à être une preuve de concept, et dans un souci de clarté et de concentration, il reste pertinent en omettant un code non lié important. Veuillez ne pas simplement le copier-coller aveuglément.
J'avais besoin de la transition pour répéter indéfiniment. Il a fallu BEAUCOUP d'essais et d'erreurs pour celui-ci, mais j'ai finalement obtenu le résultat final que je recherchais. Il s'agit d'extraits de code permettant d'ajouter une animation d'image à un UIImageView dans un UITableViewCell.
Voici le code pertinent:
@interface SomeViewController ()
@property(nonatomic, strong) NSMutableArray *imagesArray;
@property(nonatomic, assign) NSInteger varietyImageAnimationIndex;
@property(nonatomic, assign) BOOL varietyImagesAnimated;
@end
@implementation SomeViewController
@synthesize imagesArray;
@synthesize varietyImageAnimationIndex;
@synthesize varietyImagesAnimated;
...
// NOTE: Initialize the array of images in perhaps viewDidLoad method.
-(void)animateImages
{
varietyImageAnimationIndex++;
[UIView transitionWithView:varietyImageView
duration:2.0f
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
varietyImageView.image = [imagesArray objectAtIndex:varietyImageAnimationIndex % [imagesArray count]];
} completion:^(BOOL finished) {
[self animateImages];
}];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
...
[cell.imageView setImage:[imagesArray objectAtIndex:0]];
[self setVarietyImageView:cell.imageView];
if (! varietyImagesAnimated)
{
varietyImagesAnimated = YES;
[self animateImages];
}
...
return cell;
}
Après avoir joué avec UIView.transition()
et avoir eu des problèmes avec l' .transitionCrossDissolve
option (j'essayais d'animer des images changeant à l'intérieur d'une UIImageView et la transition s'est produite instantanément sans animation), j'ai découvert qu'il vous suffit d'ajouter une option supplémentaire qui vous permet d'animer les propriétés changeant à l'intérieur de la vue ( Swift 4.2 ):
UIView.transition(with: self.imageView,
duration: 1,
options: [.allowAnimatedContent, .transitionCrossDissolve],
animations: { self.imageView.image = newImage },
completion: nil)
De plus: si vous avez des sous-vues sur votre imageView, elle sera également redessinée et cela pourrait empêcher l'animation. Par exemple, j'avais une sous-vue avec un flou sur mon imageView et dans ce cas, l'animation ne fonctionne pas. Je viens donc de changer ma hiérarchie de vue et de déplacer le flou vers sa propre vue et de le placer sur imageView.
En utilisant la highlightedImage
propriété, cela peut être rendu un peu plus simple. Voici un exemple dans Swift 3. Commencez par définir à la fois l'image normale et surlignée:
let imageView = UIImageView(image: UIImage(named: "image"), highlightedImage: UIImage(named: "highlightedImage"))
Et quand vous voulez changer entre ceux animés:
UIView.transition(with: imageView, duration: 0.3, options: .transitionCrossDissolve, animations: { self.imageView.isHighlighted = !self.imageView.isHighlighted}, completion: .none)