更改UIImageView图像时淡化/溶解

时间:2011-10-03 18:03:54

标签: ios objective-c swift cocoa-touch uiimageview

不是创建两个UIImageViews,而是简单地更改一个视图的image似乎是合乎逻辑的。如果我这样做,那么两个图像之间是否有淡入淡出/交叉消解而不是即时切换?

9 个答案:

答案 0 :(得分:570)

使用新的基于块的UIKit动画方法可以简单得多。

假设以下代码在视图控制器中,并且您想要交叉解散的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.0

 let toImage = UIImage(named:"myname.png")
 UIView.transition(with: self.imageView,
                   duration: 0.3,
                   options: .transitionCrossDissolve,
                   animations: {
                       self.imageView.image = toImage
                   },
                   completion: nil)

答案 1 :(得分:44)

编辑:@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

答案 2 :(得分:6)

是的,你说的是绝对正确的,这就是做到这一点的方法。我写了这个方法&总是用它来淡化我的形象。我为此处理了CALayer。您需要为此导入Core Animation。

+ (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;
}

你可以做相反的淡出图像。它淡出后。您只需将其从superview(UIImageView)中删除即可。 [imageView removeFromSuperview]

答案 3 :(得分:6)

对于Swift 3.0.1:

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

参考:https://gist.github.com/licvido/bc22343cacfa3a8ccf88

答案 4 :(得分:4)

您还可以将淡入功能打包在子类中,以便您可以将其用作常见的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:函数中实际实现淡入的方式可能会发生变化,并且可能是此问题的其他答案中描述的其他优秀示例之一 - 创建一个额外的在我这里做的飞行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),仅用作概念证明,并且为了清晰和重点,它通过省略重要的无关而保持相关性码。请不要盲目地复制粘贴。

答案 5 :(得分:3)

我需要过渡无限期地重复。这个问题经过了大量的反复试验,但我终于找到了我想要的最终结果。这些是用于将图像动画添加到UITableViewCell中的UIImageView的代码片段。

以下是相关代码:

@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;
}

答案 6 :(得分:1)

在使用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上。

答案 7 :(得分:0)

这是我认为最短的做法。创建一个UIView动画并将其提交到您的imageView。

[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
[myImageView setAlpha:0.0];
[UIView commitAnimations];

答案 8 :(得分:0)

通过使用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)