Em vez de criar duas UIImageViews
, parece lógico simplesmente alterar a image
visão de uma. Se eu fizer isso, existe uma forma de dissolver / desvanecer / dissolver entre as duas imagens em vez de uma troca instantânea?
Em vez de criar duas UIImageViews
, parece lógico simplesmente alterar a image
visão de uma. Se eu fizer isso, existe uma forma de dissolver / desvanecer / dissolver entre as duas imagens em vez de uma troca instantânea?
Respostas:
Edit: existe uma solução melhor em @algal abaixo .
Outra maneira de fazer isso é usar transições predefinidas do CAAnimation:
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;
Consulte o projeto de exemplo View Transitions da Apple: https://developer.apple.com/library/content/samplecode/ViewTransitions/Introduction/Intro.html#//apple_ref/doc/uid/DTS40007411
Pode ser muito mais simples usar os novos UIKit animation
métodos baseados em blocos .
Suponha que o código a seguir esteja no controlador de exibição, e o UIImageView que você deseja dissolver é uma subvisão de self.view endereçável por meio da propriedade self.imageView
Então, tudo o que você precisa é:
UIImage * toImage = [UIImage imageNamed:@"myname.png"];
[UIView transitionWithView:self.imageView
duration:5.0f
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
self.imageView.image = toImage;
} completion:nil]
Feito.
E para fazer isso no Swift, é assim:
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 e 5
let toImage = UIImage(named:"myname.png")
UIView.transition(with: self.imageView,
duration: 0.3,
options: .transitionCrossDissolve,
animations: {
self.imageView.image = toImage
},
completion: nil)
Para o Swift 3.0.1:
UIView.transition(with: self.imageView,
duration:0.5,
options: .transitionCrossDissolve,
animations: { self.imageView.image = newImage },
completion: nil)
Referência: https://gist.github.com/licvido/bc22343cacfa3a8ccf88
Sim, o que você diz é absolutamente correto e é esse o caminho. Eu escrevi esse método e sempre o uso para desaparecer na minha imagem. Eu lido com CALayer
isso. Você precisa importar o Core Animation para isso.
+ (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;
}
Você pode fazer o oposto para desvanecer uma imagem. Depois que desaparece. Você acabou de removê-lo da superview (que é UIImageView
). [imageView removeFromSuperview]
.
Você também pode empacotar o recurso de desvanecimento em uma subclasse, para poder usá-lo como um UIImageView comum, como no exemplo a seguir:
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
Uma possível implementação a seguir.
Nota: a maneira como você realmente implementa o desvanecimento na setImage:
função pode mudar e pode ser um dos outros excelentes exemplos descritos nas outras respostas a esta pergunta - criando um adicional imediato, UIImageView
como eu estou fazendo aqui. ser uma sobrecarga inaceitável na sua situação específica .
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];
}];
}
}
O código acima baseia-se em algumas suposições (incluindo a ativação do ARC no seu projeto XCode), destina-se apenas como uma prova de conceito e, por questões de clareza e foco, permanece relevante ao omitir códigos não relacionados importantes. Por favor, não copie e cole cegamente.
Eu precisava que a transição se repetisse indefinidamente. Foram necessárias muitas tentativas e erros para este, mas finalmente consegui o resultado final que estava procurando. Esses são trechos de código para adicionar animação de imagem a um UIImageView em um UITableViewCell.
Aqui está o código relevante:
@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;
}
Depois de brincar UIView.transition()
e ter problemas com a .transitionCrossDissolve
opção (eu estava tentando animar as imagens que mudam dentro de um UIImageView e a transição ocorreu instantaneamente sem animação), descobri que você só precisa adicionar mais uma opção, que permite animar as propriedades que mudam dentro da exibição ( Swift 4.2 ):
UIView.transition(with: self.imageView,
duration: 1,
options: [.allowAnimatedContent, .transitionCrossDissolve],
animations: { self.imageView.image = newImage },
completion: nil)
Além disso: se você tiver subviews no imageView, ele também será redesenhado e poderá impedir a animação. Por exemplo, eu tive uma subvisão com desfoque no meu imageView e, nesse caso, a animação não funciona. Então, mudei minha hierarquia de vistas e movi o desfoque para sua própria vista e a coloquei sobre o imageView.
Usando a highlightedImage
propriedade, isso pode ser um pouco mais simples. Aqui está um exemplo no Swift 3. Primeiro, defina a imagem normal e a destacada:
let imageView = UIImageView(image: UIImage(named: "image"), highlightedImage: UIImage(named: "highlightedImage"))
E quando você quiser alternar entre os animados:
UIView.transition(with: imageView, duration: 0.3, options: .transitionCrossDissolve, animations: { self.imageView.isHighlighted = !self.imageView.isHighlighted}, completion: .none)