【问题标题】:Make a simple fade in animation in Swift?在 Swift 中做一个简单的淡入淡出动画?
【发布时间】:2014-07-29 11:47:15
【问题描述】:

我正在尝试用 Swift 制作一个简单的动画。这是一个淡入。

我尝试过:

self.myFirstLabel.alpha = 0
self.myFirstButton.alpha = 0
self.mySecondButton.alpha = 0

那么,我有:

self.view.addSubview(myFirstLabel)
self.view.addSubview(myFirstButton)
self.view.addSubview(mySecondButton)

然后:

UIView.animateWithDuration(1.5, animations: {
 self.myFirstLabel.alpha = 1.0
 self.myFirstButton.alpha = 1.0
 self.mySecondButton.alpha = 1.0
})

我的 viewDidLoad 函数中包含所有这些。

我该如何进行这项工作?

【问题讨论】:

  • 所有元素同时进入。就在视图加载时。
  • 您确定这些视图在 xib 中正确连接了吗?
  • 我没有使用 IB。一切都是程序化的。
  • 从你提供的代码来看,一切都应该正常工作(这与 Swift 无关)。其他地方一定有错误。
  • 考虑将视图外观方法调用移动到viewWillAppearviewDidAppear,因为您不知道视图加载和显示之间会发生什么。

标签: ios swift


【解决方案1】:

问题是您尝试在视图控制器的生命周期中过早启动动画。在viewDidLoad 中,视图刚刚创建,尚未添加到视图层次结构中,因此此时尝试为其subviews 之一设置动画会产生不良结果。

您真正应该做的是继续在viewDidLoad(或您创建视图的位置)中设置视图的alpha,然后等待调用viewDidAppear: 方法。此时,您可以毫无问题地开始制作动画。

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    UIView.animate(withDuration: 1.5) {
        self.myFirstLabel.alpha = 1.0
        self.myFirstButton.alpha = 1.0
        self.mySecondButton.alpha = 1.0
    }
}

【讨论】:

  • viewWillAppear 更适合这个吗?
  • 记住,如果你只有1条语句,你需要添加一个return UIView.animateWithDuration(1.5, animations: { self.myFirstLabel.alpha = 1.0 return })
  • @oshevans 你是指需要在闭包末尾添加return语句吗?这在最新的 Xcode 版本中大部分已得到修复。
  • 我有一个非常相似的错误。请看看你是否可以帮助我:stackoverflow.com/questions/29910669/…
  • @0x7fffffff '...大部分是固定的...' - 这听起来不太乐观; / 尚未从 6.2 更新
【解决方案2】:

0x7ffffff 的回答还可以,而且绝对详尽。

另外,我建议你用这种方式制作一个 UIView 扩展:

public extension UIView {

  /**
  Fade in a view with a duration

  - parameter duration: custom animation duration
  */
  func fadeIn(duration duration: NSTimeInterval = 1.0) {
    UIView.animateWithDuration(duration, animations: {
        self.alpha = 1.0
    })
  }

  /**
  Fade out a view with a duration

  - parameter duration: custom animation duration
  */
  func fadeOut(duration duration: NSTimeInterval = 1.0) {
    UIView.animateWithDuration(duration, animations: {
        self.alpha = 0.0
    })
  }

}

Swift-3

/// Fade in a view with a duration
/// 
/// Parameter duration: custom animation duration
func fadeIn(withDuration duration: TimeInterval = 1.0) {
    UIView.animate(withDuration: duration, animations: {
        self.alpha = 1.0
    })
}

/// Fade out a view with a duration
///
/// - Parameter duration: custom animation duration
func fadeOut(withDuration duration: TimeInterval = 1.0) {
    UIView.animate(withDuration: duration, animations: {
        self.alpha = 0.0
    })
}

Swift-5

public extension UIView {

/**
 Fade in a view with a duration
 
 - parameter duration: custom animation duration
 */
 func fadeIn(duration: TimeInterval = 1.0) {
     UIView.animate(withDuration: duration, animations: {
        self.alpha = 1.0
     })
 }

/**
 Fade out a view with a duration
 
 - parameter duration: custom animation duration
 */
func fadeOut(duration: TimeInterval = 1.0) {
    UIView.animate(withDuration: duration, animations: {
        self.alpha = 0.0
    })
  }

}

通过这种方式,您可以在代码中的任何位置执行此操作:

let newImage = UIImage(named: "")
newImage.alpha = 0 // or newImage.fadeOut(duration: 0.0)
self.view.addSubview(newImage)
... 
newImage.fadeIn()

代码重用很重要!

【讨论】:

    【解决方案3】:

    Swift 唯一解决方案

    类似于Luca's anwer,我使用UIView 扩展名。与他的解决方案相比,我使用DispatchQueue.main.async 确保动画在主线程上完成,alpha 参数用于淡入特定值,可选duration 参数用于更简洁的代码。

    extension UIView {
      func fadeTo(_ alpha: CGFloat, duration: TimeInterval = 0.3) {
        DispatchQueue.main.async {
          UIView.animate(withDuration: duration) {
            self.alpha = alpha
          }
        }
      }
    
      func fadeIn(_ duration: TimeInterval = 0.3) {
        fadeTo(1.0, duration: duration)
      }
    
      func fadeOut(_ duration: TimeInterval = 0.3) {
        fadeTo(0.0, duration: duration)
      }
    }
    

    如何使用:

    // fadeIn() - always animates to alpha = 1.0
    yourView.fadeIn()     // uses default duration of 0.3
    yourView.fadeIn(1.0)  // uses custom duration (1.0 in this example)
    
    // fadeOut() - always animates to alpha = 0.0
    yourView.fadeOut()    // uses default duration of 0.3
    yourView.fadeOut(1.0) // uses custom duration (1.0 in this example)
    
    // fadeTo() - used if you want a custom alpha value
    yourView.fadeTo(0.5)  // uses default duration of 0.3
    yourView.fadeTo(0.5, duration: 1.0)
    

    【讨论】:

      【解决方案4】:

      如果您想要可重复的淡入淡出动画,您可以使用CABasicAnimation 来实现,如下所示:

      首先创建方便的 UIView 扩展:

      extension UIView {
      
          enum AnimationKeyPath: String {
              case opacity = "opacity"
          }
      
          func flash(animation: AnimationKeyPath ,withDuration duration: TimeInterval = 0.5, repeatCount: Float = 5){
              let flash = CABasicAnimation(keyPath: animation.rawValue)
              flash.duration = duration
              flash.fromValue = 1 // alpha
              flash.toValue = 0 // alpha
              flash.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
              flash.autoreverses = true
              flash.repeatCount = repeatCount
      
              layer.add(flash, forKey: nil)
          }
      }
      

      使用方法:

          // You can use it with all kind of UIViews e.g. UIButton, UILabel, UIImage, UIImageView, ...
          imageView.flash(animation: .opacity, withDuration: 1, repeatCount: 5)
          titleLabel.flash(animation: .opacity, withDuration: 1, repeatCount: 5)
      

      【讨论】:

        【解决方案5】:
        import UIKit
        
        /*
         Here is simple subclass for CAAnimation which create a fadeIn animation
         */
        
        class FadeInAdnimation: CABasicAnimation {
            override init() {
                super.init()
                keyPath = "opacity"
                duration = 2.0
                fromValue = 0
                toValue = 1
                fillMode = CAMediaTimingFillMode.forwards
                isRemovedOnCompletion = false
            }
        
            required init?(coder aDecoder: NSCoder) {
                super.init(coder: aDecoder)
            }
        }
        
        /*
         Example of usage
         */
        
        class ViewController: UIViewController {
        
            weak var label: UILabel!
        
            override func loadView() {
                let view = UIView()
                view.backgroundColor = .white
        
                let label = UILabel()
                label.alpha = 0
                label.frame = CGRect(x: 150, y: 200, width: 200, height: 20)
                label.text = "Hello World!"
                label.textColor = .black
                view.addSubview(label)
                self.label = label
        
                let button = UIButton(type: .custom)
                button.frame = CGRect(x: 0, y: 250, width: 300, height: 100)
                button.setTitle("Press to Start FadeIn", for: UIControl.State())
                button.backgroundColor = .red
                button.addTarget(self, action: #selector(startFadeIn), for: .touchUpInside)
                view.addSubview(button)
        
                self.view = view
            }
        
            /*
             Animation in action
             */
            @objc private func startFadeIn() {
                label.layer.add(FadeInAdnimation(), forKey: "fadeIn")
            }
        
        }
        

        【讨论】:

          【解决方案6】:

          斯威夫特 5

          其他答案是正确的,但就我而言,我还需要处理其他属性(alphaanimatecompletion)。正因为如此,我做了一些修改,将这些参数公开如下:

          extension UIView {
              /// Helper function to update view's alpha with animation
              /// - Parameter alpha: View's alpha
              /// - Parameter animate: Indicate alpha changing with animation or not
              /// - Parameter duration: Indicate time for animation
              /// - Parameter completion: Completion block after alpha changing is finished
              func set(alpha: CGFloat, animate: Bool, duration: TimeInterval = 0.3, completion: ((Bool) -> Void)? = nil) {
                  let animation = { (view: UIView) in
                      view.alpha = alpha
                  }
              
                  if animate {
                      UIView.animate(withDuration: duration, animations: {
                          animation(self)
                      }, completion: { finished in
                          completion?(finished)
                      })
                  } else {
                      layer.removeAllAnimations()
                      animation(self)
                      completion?(true)
                  }
              }
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-01-20
            • 2012-12-18
            • 2010-12-17
            • 1970-01-01
            • 2019-02-11
            • 1970-01-01
            相关资源
            最近更新 更多