Ios 更改UIImageView时淡入/消失';s形象

Ios 更改UIImageView时淡入/消失';s形象,ios,objective-c,swift,cocoa-touch,uiimageview,Ios,Objective C,Swift,Cocoa Touch,Uiimageview,与其创建两个uiimageview,不如简单地更改一个视图的图像。如果我这样做,两幅图像之间是否存在淡入淡出/交叉融合,而不是即时切换?是的,你所说的绝对正确,这就是解决方法。我写了这个方法&总是用这个在我的图像中淡出。为此,我处理了CALayer。您需要为此导入核心动画 + (void)fadeInLayer:(CALayer *)l { CABasicAnimation *fadeInAnimate = [CABasicAnimation animationWithKeyPath

与其创建两个
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;
}

对于淡出图像,您可以执行相反的操作。在它消失之后。您只需将其从superview(即
UIImageView
)中删除即可
[imageView removeFromSuperview]

编辑:从中有更好的解决方案。

另一种方法是使用预定义的动画转换:

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示例项目:

使用新的基于块的UIKit animation
方法可能会简单得多

假设以下代码位于视图控制器中,并且要交叉分解的UIImageView是self.view的子视图,可通过属性
self.imageView
进行寻址,那么您只需要:

UIImage*toImage=[UIImage-imagename:@“myname.png”];
[UIView转换WithView:self.imageView
持续时间:5.0华氏度
选项:UIViewAnimationOptionTransitionCrossSolve
动画:^{
self.imageView.image=toImage;
}完成日期:无]
完成了

在Swift中,它是这样做的:

让toImage=UIImage(名为:“myname.png”)
UIView.transitionWithView(self.imageView,
持续时间:5,
选项:UIViewAnimationOptions.TransitionCrossSolve,动画:{self.imageView.image=toImage},完成:nil)
Swift 3、4和5

让toImage=UIImage(名为:“myname.png”)
UIView.transition(使用:self.imageView,
持续时间:0.3,
选项:。传递交叉溶解,
动画:{self.imageView.image=toImage},
完成:无)

您还可以将淡入功能打包到一个子类中,这样您就可以将其用作常见的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
#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];
        }];
    }
}
#导入
@接口IMMFadeImageView:UIImageView
@属性(非原子,赋值)浮点衰减;
@结束
IMMFadeImageView.m

#import <UIKit/UIKit.h>

@interface IMMFadeImageView : UIImageView
@property (nonatomic,assign) float fadeDuration;
@end
#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];
        }];
    }
}
#导入“IMMFadeImageView.h”
@实现IMMFadeImageView
@综合衰减;
-(id)initWithFrame:(CGRect)帧
{
self=[super initWithFrame:frame];
如果(自我){
自衰减=1;
}
回归自我;
}
-(void)setImage:(UIImage*)newImage{

如果(!self.image | | self.fadeDuration我需要无限期地重复转换。这一次经历了很多尝试和错误,但我最终得到了我想要的最终结果。这些是在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;
}

这是我认为最简单的方法。创建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()
之后,发现
选项出现了问题。transitionCrossResolve
选项(我试图在一个UIImageView中设置图像更改的动画,但在没有动画的情况下立即发生了转换)我发现,您只需再添加一个选项,即可为视图中更改的属性设置动画(Swift 4.2):


此外:如果您的imageView上有任何子视图,它也将被重新绘制,这可能会阻止动画。例如,我的imageView上有一个带有模糊的子视图,在这种情况下,动画不起作用。所以我只是更改了我的视图层次结构,将模糊移动到自己的视图,并将其置于imageView上。

其他答案是正确的,但不正确ted(和/或过于冗长)。没有必要在超级视图上进行转换。我通过将UIImageView本身指定为目标来实现这一点。@user577888只是一件小事。您应该将nil传递给空的完成块。块不是函数指针(由^表示)并像objective-c对象一样操作。如果传递NULL,编译器将解释为0或(void*)0。如果出于某种原因,transitionWithView的底层代码:…意外地向完成块发送消息(例如,[完成副本])如果不检查其有效性,这将导致错误。因此,在将块设置为空时,应始终使用objective-c的nil。@Mr.T NULL和nil的值相同。两者都定义为0,并且都不可能更改。因此,在任何可能使用或可以使用nil的地方使用NULL都是安全的。@Mr.T我的观点是,在整个过程中使用一个NULL另一个永远不会导致崩溃,因为在编译代码级别,它们是相同的,并且出于实际原因,它们总是相同的。一般来说,抑制编译器警告是一个好主意,但告诉人们使用NULL而不是nil是错误的。太好了!我将此代码的一部分添加到SDWebImage的UIImageView(WebCache)中类别。@OutMan用户577888最好使用下面更新的方法。我还在SDWe后设置图像
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
[myImageView setAlpha:0.0];
[UIView commitAnimations];