我正在尝试在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函数中拥有所有这些。
如何使这项工作?
答案 0 :(得分:88)
问题是你在视图控制器的生命周期中过早地尝试启动动画。在viewDidLoad中,视图刚刚创建,尚未添加到视图层次结构中,因此此时尝试为其中一个子视图设置动画会产生不良结果。
你真正应该做的是继续在viewDidLoad中设置视图的alpha(或创建视图的位置),然后等待viewDidAppear:方法被调用。此时,您可以毫无问题地开始制作动画。
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
UIView.animateWithDuration(1.5, animations: {
self.myFirstLabel.alpha = 1.0
self.myFirstButton.alpha = 1.0
self.mySecondButton.alpha = 1.0
})
}
答案 1 :(得分:43)
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
})
}
}
夫特-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
})
}
通过这种方式,您可以在代码中的任何地方:
let newImage = UIImage(named: "")
newImage.alpha = 0 // or newImage.fadeOut(duration: 0.0)
self.view.addSubview(newImage)
...
newImage.fadeIn()
代码重用很重要!
答案 2 :(得分:2)
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 != nil ? duration! : 0.3) {
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)
答案 3 :(得分:1)
如果您想要可重复的淡入淡出动画,则可以使用CABasicAnimation
进行如下操作:
extension UIView {
enum AnimationKeyPath: String {
case opacity = "opacity"
}
func flash(animation: AnimationKeyPath ,withDuration duration: TimeInterval = 0.5, repeatCount: Float = 5){
let flash = CABasicAnimation(keyPath: AnimationKeyPath.opacity.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)
答案 4 :(得分:0)
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")
}
}
答案 5 :(得分:0)
其他答案是正确的,但就我而言,我还需要处理其他属性(alpha
,animate
,completion
)。因此,我做了一些修改以显示以下参数:
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)
}
}
}