简体   繁体   English

如何为 UIImageView 中的图像变化设置动画?

[英]How to animate the change of image in an UIImageView?

I have an UIImageView with an image.我有一个带有图像的UIImageView Now I have a completely new image (graphic file), and want to display that in this UIImageView .现在我有一个全新的图像(图形文件),并想在这个UIImageView显示它。 If I just set如果我只是设置

myImageView.image = newImage;

the new image is visible immediately.新图像立即可见。 Not animatable.不可动画。

I want it to nicely fade into the new image.我希望它很好地淡入新图像中。 I thought maybe there's a better solution than just creating a new UIImageView on top of that and blending with animation?我想也许有更好的解决方案,而不仅仅是在其上创建一个新的UIImageView并与动画混合?

[UIView transitionWithView:textFieldimageView
                  duration:0.2f
                   options:UIViewAnimationOptionTransitionCrossDissolve
                animations:^{
                    imageView.image = newImage;
                } completion:nil];

is another possibility是另一种可能

I am not sure if you can animate UIViews with fade effect as it seems all supported view transitions are defined in UIViewAnimationTransition enumeration.我不确定您是否可以使用淡入淡出效果为 UIViews 设置动画,因为似乎所有支持的视图转换都在UIViewAnimationTransition枚举中定义。 Fading effect can be achieved using CoreAnimation.使用 CoreAnimation 可以实现淡入淡出效果。 Sample example for this approach:此方法的示例示例:

#import <QuartzCore/QuartzCore.h>
...
imageView.image = [UIImage imageNamed:(i % 2) ? @"3.jpg" : @"4.jpg"];

CATransition *transition = [CATransition animation];
transition.duration = 1.0f;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionFade;

[imageView.layer addAnimation:transition forKey:nil];

In the words of Michael Scott, keep it simple stupid.用迈克尔斯科特的话来说,保持简单愚蠢。 Here is a simple way to do this in Swift 3 and Swift 4 :这是在Swift 3Swift 4 中执行此操作的简单方法:

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

Here is one example in Swift that will first cross dissolve a new image and then add a bouncy animation:这是Swift中的一个示例,它首先交叉溶解一张新图像,然后添加一个有弹性的动画:

var selected: Bool {
  willSet(selected) {
    let expandTransform:CGAffineTransform = CGAffineTransformMakeScale(1.15, 1.15);
    if (!self.selected && selected) {
      UIView.transitionWithView(self.imageView,
        duration:0.1,
        options: UIViewAnimationOptions.TransitionCrossDissolve,
        animations: {
          self.imageView.image = SNStockCellSelectionAccessoryViewImage(selected)
          self.imageView.transform = expandTransform
        },
        completion: {(finished: Bool) in
          UIView.animateWithDuration(0.4,
            delay:0.0,
            usingSpringWithDamping:0.40,
            initialSpringVelocity:0.2,
            options:UIViewAnimationOptions.CurveEaseOut,
            animations: {
              self.imageView.transform = CGAffineTransformInvert(expandTransform)
            }, completion:nil)
      })
    }
  }
}

var imageView:UIImageView

If imageView is correctly added to the view as a subview, toggling between selected = false to selected = true should swap the image with a bouncy animation.如果imageView作为子视图正确添加到视图中,则在selected = falseselected = true之间切换应该用有弹性的动画交换图像。 SNStockCellSelectionAccessoryViewImage just returns a different image based on the current selection state, see below: SNStockCellSelectionAccessoryViewImage只是根据当前选择状态返回不同的图像,见下文:

private let SNStockCellSelectionAccessoryViewPlusIconSelected:UIImage = UIImage(named:"PlusIconSelected")!
private let SNStockCellSelectionAccessoryViewPlusIcon:UIImage = UIImage(named:"PlusIcon")!

private func SNStockCellSelectionAccessoryViewImage(selected:Bool) -> UIImage {
  return selected ? SNStockCellSelectionAccessoryViewPlusIconSelected : SNStockCellSelectionAccessoryViewPlusIcon
}

The GIF example below is a bit slowed down, the actual animation happens faster:下面的 GIF 示例有点慢,实际动画发生得更快:

UIImageView 弹跳动画 Gif

Code:代码:

var fadeAnim:CABasicAnimation = CABasicAnimation(keyPath: "contents");

fadeAnim.fromValue = firstImage;
fadeAnim.toValue   = secondImage;
fadeAnim.duration  = 0.8;         //smoothest value

imageView.layer.addAnimation(fadeAnim, forKey: "contents");

imageView.image = secondImage;

Example:例子:

代码中的 UIImageView 示例

Fun, More Verbose Solution : ( Toggling on a tap )有趣,更详细的解决方案:(点击切换

    let fadeAnim:CABasicAnimation = CABasicAnimation(keyPath: "contents");

    switch imageView.image {
        case firstImage?:
            fadeAnim.fromValue = firstImage;
            fadeAnim.toValue   = secondImage;
            imageView.image    = secondImage;
        default:
            fadeAnim.fromValue = secondImage;
            fadeAnim.toValue   = firstImage;
            imageView.image    = firstImage;
    }

    fadeAnim.duration = 0.8;

    imageView.layer.addAnimation(fadeAnim, forKey: "contents");

Swift 5 extension:斯威夫特 5扩展:

extension UIImageView{
    func setImage(_ image: UIImage?, animated: Bool = true) {
        let duration = animated ? 0.3 : 0.0
        UIView.transition(with: self, duration: duration, options: .transitionCrossDissolve, animations: {
            self.image = image
        }, completion: nil)
    }
}
 

Try this:尝试这个:

_imageView.image = image;
[_imageView.layer addAnimation:[CATransition animation] forKey:kCATransition];

With Swift 3使用 Swift 3

extension UIImageView{   
 var imageWithFade:UIImage?{
        get{
            return self.image
        }
        set{
            UIView.transition(with: self,
                              duration: 0.5, options: .transitionCrossDissolve, animations: {
                                self.image = newValue
            }, completion: nil)
        }
    }
}

Usage:用法:

myImageView.imageWithFade = myImage

Why not try this.为什么不试试这个。

NSArray *animationFrames = [NSArray arrayWithObjects:
  [UIImage imageWithName:@"image1.png"],
  [UIImage imageWithName:@"image2.png"], 
  nil];

UIImageView *animatedImageView = [[UIImageView alloc] init];
animatedImageView.animationImages = animationsFrame;
[animatedImageView setAnimationRepeatCount:1];
[animatedImageView startAnimating];

A swift version:一个快速版本:

let animationsFrames = [UIImage(named: "image1.png"), UIImage(named: "image2.png")]
let animatedImageView = UIImageView()
animatedImageView.animationImages = animationsFrames
animatedImageView.animationRepeatCount = 1
animatedImageView.startAnimating()
CABasicAnimation* fadeAnim = [CABasicAnimation animationWithKeyPath:@"contents"];
fadeAnim.fromValue = (__bridge id)imageView.image.CGImage;
fadeAnim.toValue = (__bridge id)[UIImage imageNamed:@"newImage.png"].CGImage;
fadeAnim.duration = 2.0;
[imageView.layer addAnimation:fadeAnim forKey:@"contents"];
imageView.layer.contents = (__bridge id)[UIImage imageNamed:@"newImage.png"].CGImage;

Swift 4 This is just awesome Swift 4这真是太棒了

  self.imgViewPreview.transform = CGAffineTransform(scaleX: 0, y: 0)
          UIView.animate(withDuration: 1, delay: 0, usingSpringWithDamping: 0.3, initialSpringVelocity: 0, options: .curveEaseOut, animations: {
              self.imgViewPreview.image = newImage
              self.imgViewPreview.transform = .identity
          }, completion: nil)

There are a few different approaches here: UIAnimations to my recollection it sounds like your challenge.这里有几种不同的方法: UIAnimations在我的记忆中,这听起来像是你的挑战。

Edit: too lazy of me:)编辑:我太懒了:)

In the post, I was referring to this method:在帖子中,我指的是这种方法:

[newView setFrame:CGRectMake( 0.0f, 480.0f, 320.0f, 480.0f)]; //notice this is OFF screen!
[UIView beginAnimations:@"animateTableView" context:nil];
[UIView setAnimationDuration:0.4];
[newView setFrame:CGRectMake( 0.0f, 0.0f, 320.0f, 480.0f)]; //notice this is ON screen!
[UIView commitAnimations];

But instead of animation the frame, you animate the alpha:但不是动画帧,而是动画 alpha:

[newView setAlpha:0.0]; // set it to zero so it is all gone.
[UIView beginAnimations:@"animateTableView" context:nil];
[UIView setAnimationDuration:0.4];
[newView setAlpha:0.5]; //this will change the newView alpha from its previous zero value to 0.5f
[UIView commitAnimations];

As of iOS 5 this one is far more easy:从 iOS 5 开始,这要容易得多:

[newView setAlpha:0.0];
[UIView animateWithDuration:0.4 animations:^{
    [newView setAlpha:0.5];
}];

Vladimir's answer is perfect, but anyone like me who is looking for swift solution弗拉基米尔的回答是完美的,但像我这样正在寻找快速解决方案的人

This Solution is Worked for swift version 4.2此解决方案适用于swift 4.2 版

var i = 0
    func animation(){
        let name = (i % 2 == 0) ? "1.png" : "2.png"
        myImageView.image = UIImage.init(named: name)
        let transition: CATransition = CATransition.init()
        transition.duration = 1.0
        transition.timingFunction = CAMediaTimingFunction.init(name: .easeInEaseOut)
        transition.type = .fade
        myImageView.layer.add(transition, forKey: nil)
        i += 1
    }

You can call this method from anywhere.您可以从任何地方调用此方法。 It will change the image to next one(image) with animation.它将通过动画将图像更改为下一个(图像)。

For Swift Version 4.0 Use bellow solution对于Swift 4.0 版,请使用以下解决方案

var i = 0
    func animationVersion4(){
        let name = (i % 2 == 0) ? "1.png" : "2.png"
        uiImage.image = UIImage.init(named: name)
        let transition: CATransition = CATransition.init()
        transition.duration = 1.0
        transition.timingFunction = CAMediaTimingFunction.init(name: kCAMediaTimingFunctionEaseInEaseOut)
        transition.type = kCATransitionFade
        uiImage.layer.add(transition, forKey: nil)
        i += 1
    }

Swift 5:斯威夫特 5:

When deal with collectionView.处理 collectionView 时。 Reloading only 1 item or several items with animation.仅重新加载 1 个或多个带有动画的项目。 I try some different animation options when changing cell image, no difference, so I don't indicate animation name here.我在更改单元格图像时尝试了一些不同的动画选项,没有区别,所以我在这里不指明动画名称。

UIView.animate(withDuration: 1.0) { [weak self] in
                guard let self = self else { return print("gotchya!") }
                self.collectionView.reloadItems(at: [indexPath])
            }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM