【发布时间】:2011-11-30 03:07:26
【问题描述】:
与其创建两个UIImageViews,不如简单地更改一个视图的image 似乎是合乎逻辑的。如果我这样做,是否有两个图像之间的淡入淡出/交叉溶解而不是即时切换?
【问题讨论】:
标签: ios objective-c swift cocoa-touch uiimageview
与其创建两个UIImageViews,不如简单地更改一个视图的image 似乎是合乎逻辑的。如果我这样做,是否有两个图像之间的淡入淡出/交叉溶解而不是即时切换?
【问题讨论】:
标签: ios objective-c swift cocoa-touch uiimageview
是的,您所说的绝对正确,这就是这样做的方法。我写了这个方法并总是用它来淡入我的图像。我为此处理CALayer。您需要为此导入核心动画。
+ (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;
}
您可以对淡出图像执行相反的操作。淡出之后。您只需将其从超级视图(UIImageView)中删除。 [imageView removeFromSuperview].
【讨论】:
编辑:@algal below 有更好的解决方案。
另一种方法是使用预定义的 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;
查看 Apple 的 View Transitions 示例项目:https://developer.apple.com/library/content/samplecode/ViewTransitions/Introduction/Intro.html#//apple_ref/doc/uid/DTS40007411
【讨论】:
使用新的基于块的UIKit animation 方法可以更简单。
假设以下代码在视图控制器中,而您要交叉溶解的 UIImageView 是 self.view 的子视图,可通过属性self.imageView 寻址,那么您只需要:
UIImage * toImage = [UIImage imageNamed:@"myname.png"];
[UIView transitionWithView:self.imageView
duration:5.0f
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
self.imageView.image = toImage;
} completion:nil]
完成。
要在 Swift 中完成,就像这样:
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 和 5
let toImage = UIImage(named:"myname.png")
UIView.transition(with: self.imageView,
duration: 0.3,
options: .transitionCrossDissolve,
animations: { self.imageView.image = toImage },
completion: nil)
【讨论】:
您也可以将淡入功能封装在一个子类中,这样您就可以将其用作通用的 UIImageView,如下例所示:
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
一个可能的实现如下。
注意:您在 setImage: 函数中实际实现淡入的方式可能会发生变化,并且可能是该问题的其他答案中描述的其他优秀示例之一 — 创建一个额外的 on-the -fly UIImageView 就像我在这里所做的那样,在您的特定情况下可能是不可接受的开销。
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];
}];
}
}
上述代码依赖于一些假设(包括在您的 XCode 项目中启用 ARC),仅用作概念证明,并且为了清晰和集中,它通过省略重要的不相关来保持相关性代码。请不要盲目地复制粘贴。
【讨论】:
我需要无限期地重复过渡。这需要大量的试验和错误,但我终于得到了我正在寻找的最终结果。这些是用于向 UITableViewCell 中的 UIImageView 添加图像动画的代码 sn-ps。
以下是相关代码:
@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;
}
【讨论】:
这是我认为最短的方法。创建一个 UIView 动画并将其提交到您的 imageView。
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
[myImageView setAlpha:0.0];
[UIView commitAnimations];
【讨论】:
通过使用highlightedImage 属性,这可以变得更简单一些。这是 Swift 3 中的一个示例。首先设置正常和突出显示的图像:
let imageView = UIImageView(image: UIImage(named: "image"), highlightedImage: UIImage(named: "highlightedImage"))
当你想在那些动画之间切换时:
UIView.transition(with: imageView, duration: 0.3, options: .transitionCrossDissolve, animations: { self.imageView.isHighlighted = !self.imageView.isHighlighted}, completion: .none)
【讨论】:
对于 Swift 3.0.1:
UIView.transition(with: self.imageView,
duration:0.5,
options: .transitionCrossDissolve,
animations: { self.imageView.image = newImage },
completion: nil)
【讨论】:
在玩弄UIView.transition() 并遇到.transitionCrossDissolve 选项的问题后(我试图在一个 UIImageView 内对图像进行动画更改,并且在没有动画的情况下立即发生过渡)我发现您只需要再添加一个选项,即让您在视图内更改属性的动画(Swift 4.2):
UIView.transition(with: self.imageView,
duration: 1,
options: [.allowAnimatedContent, .transitionCrossDissolve],
animations: { self.imageView.image = newImage },
completion: nil)
此外:如果您的 imageView 上有任何子视图,它也会被重绘,并且可能会阻止动画。例如,我的 imageView 上有模糊的子视图,在这种情况下动画不起作用。所以我只是改变了我的视图层次结构并将模糊移动到它自己的视图并将它放在 imageView 上。
【讨论】: