【问题标题】:How to animate the change of image in an UIImageView?如何为 UIImageView 中的图像变化设置动画?
【发布时间】:2011-02-19 13:05:30
【问题描述】:

我有一个带有图像的UIImageView。现在我有一个全新的图像(图形文件),并想在这个UIImageView 中显示它。如果我只是设置

myImageView.image = newImage;

新图像立即可见。不可动画。

我希望它很好地淡入新图像。我想也许有比仅仅创建一个新的UIImageView 并与动画混合更好的解决方案?

【问题讨论】:

标签: ios iphone animation uiimageview uiimage


【解决方案1】:

斯威夫特 5:

处理collectionView时。仅重新加载一项或几项带有动画的项目。我在更改单元格图像时尝试了一些不同的动画选项,没有区别,所以我这里不指明动画名称。

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

【讨论】:

    【解决方案2】:

    Swift 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)
        }
    }
     
    

    【讨论】:

    • 这应该是这个问题的公认答案。
    【解决方案3】:

    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)
    

    【讨论】:

      【解决方案4】:

      弗拉基米尔的回答很完美,但是像我这样正在寻找快速解决方案的人

      此解决方案适用于 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
          }
      

      您可以从任何地方调用此方法。它会将图像更改为带有动画的下一个(图像)。

      对于 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
          }
      

      【讨论】:

        【解决方案5】:

        用迈克尔斯科特的话来说,保持简单愚蠢。 这是在 Swift 3Swift 4 中执行此操作的简单方法:

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

        【讨论】:

        • 像魅力一样工作。谢谢!
        • Uau 太棒了!这么久都不知道这个该死的:)
        • 这将变为 1 张图片。如果我有一组图像并想用过渡动画逐个显示怎么办?
        • 您可以使用完成块过渡到下一个。
        • 最好的解决方案在这里!
        【解决方案6】:

        为什么不试试这个。

        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];
        

        快速版本:

        let animationsFrames = [UIImage(named: "image1.png"), UIImage(named: "image2.png")]
        let animatedImageView = UIImageView()
        animatedImageView.animationImages = animationsFrames
        animatedImageView.animationRepeatCount = 1
        animatedImageView.startAnimating()
        

        【讨论】:

        • 这会将 UIImageView 设置为永远重复切换...但是作者只是要求更改:(
        • setAnimationRepeatCount
        • SetAnimationRepeatCount 不会改变任何东西。它永远不会停止
        【解决方案7】:

        使用 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)
                }
            }
        }
        

        用法:

        myImageView.imageWithFade = myImage
        

        【讨论】:

          【解决方案8】:
          [UIView transitionWithView:textFieldimageView
                            duration:0.2f
                             options:UIViewAnimationOptionTransitionCrossDissolve
                          animations:^{
                              imageView.image = newImage;
                          } completion:nil];
          

          是另一种可能

          【讨论】:

          • 简单并在图像之间开辟了一系列其他动画效果。
          • 与@hfossli 提到的关于帧更改的问题相同。如果在此期间更改布局,动画将变得迟缓。
          • 这是最好的解决方案,因为它可以与其他动画结合使用。
          【解决方案9】:

          代码:

          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;
          

          示例:

          有趣、更详细的解决方案:(点击切换

              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");
          

          【讨论】:

            【解决方案10】:

            这是 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
            

            如果imageView 作为子视图正确添加到视图中,则在selected = falseselected = true 之间切换应该将图像与有弹性的动画交换。 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
            }
            

            下面的 GIF 例子有点慢,实际的动画发生得更快:

                                                 

            【讨论】:

              【解决方案11】:

              试试这个:

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

              【讨论】:

              • swift: _imageView.layer.addAnimation(CATransition(), forKey: kCATransition)
              【解决方案12】:
              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;
              

              【讨论】:

                【解决方案13】:

                从 iOS 5 开始,这个就简单多了:

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

                【讨论】:

                • 这对原始问题没有帮助,即您已经显示了一张图像,并且想要交叉淡入淡出到新图像......
                • 对..这个答案不能解决问题。问题不是如何在图像视图中淡入淡出,而是从旧图像淡入到新图像。 iOS 4 中引入了动画块。
                【解决方案14】:

                这里有几种不同的方法:UIAnimations 我记得这听起来像是你的挑战。

                编辑:我太懒了:)

                在帖子中,我指的是这种方法:

                [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];
                

                但不是动画帧,而是动画 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];
                

                【讨论】:

                  【解决方案15】:

                  我不确定您是否可以为 UIView 设置渐变效果,因为似乎所有支持的视图转换都在 UIViewAnimationTransition 枚举中定义。使用 CoreAnimation 可以实现淡化效果。此方法的示例:

                  #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];
                  

                  【讨论】:

                  • 您的代码在从一张图像转到另一张图像时运行良好。你知道如何让它与 UIImageView 中的图像自动动画一起工作吗(animationImages 属性)?
                  • 您可以尝试使用 CAKeyFrameAnimation 作为图层的内容属性,但不确定效果是否相同。或者设置动画委托,当上一个动画完成时,在委托回调函数中开始动画到下一个图像。
                  • 这绝对比手动交叉淡化单独的图像视图更简单。谢谢!
                  • 好吧.. 如果 imageviews 框架发生变化,那么它会保持在原来的位置.. 那是一个交易破坏者!
                  • @Fossli,您的意思是在动画期间帧发生变化时?那是一个不同的问题
                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2013-03-23
                  • 1970-01-01
                  • 2012-09-23
                  • 1970-01-01
                  相关资源
                  最近更新 更多