为实现“drawRect”的“UIView”的“backgroundColor”设置动画
Animate `backgroundColor` of a `UIView` that implements `drawRect`
我有一个自定义 UIView,我想为其设置动画 backgroundColor
属性。这是 UIView
的 animatable property。
这是代码:
class ETTimerUIView: UIView {
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
// other methods
func flashBg() {
UIView.animateWithDuration( 1.0, animations: {
self.backgroundColor = UIColor.colorYellow()
})
}
override func drawRect() {
// Something related to a timer I'm rendering
}
这段代码导致动画跳过并且颜色立即改变:
self.backgroundColor = UIColor.colorYellow() // Changes immediately to yellow
如果我对 alpha 进行动画处理,这会按预期在一秒内从 1 到 0 进行动画处理:
self.alpha = 0 // animates
在这种情况下如何为背景颜色变化设置动画?
- Implementing
drawRect
blocks backgroundColor animation,但尚未提供答案。
- Maybe this is why you can't combine
drawRect
and animateWithDuration
,但我不是很懂
我想我需要创建一个单独的视图——它应该放在同一个视图控制器的故事板中吗?以编程方式创建?
抱歉,我是 iOS 和 Swift 的新手。
当我尝试它时它确实不起作用,我有一个相关的问题,将 layoutIfNeeded() 方法放入动画中工作并使视图平滑动画(move button towards target using constraints, no reaction?)。但是在这种情况下,使用 backgroundColor 是行不通的。如果有人知道答案,我会很想知道。
但如果您现在需要一个解决方案,您可以创建一个仅用作容器的 UIView(以编程方式或通过故事板)。然后在里面添加 2 个视图:一个在上面,一个在下面,与容器具有相同的框架。你只改变顶视图的alpha,让用户看到后面的视图:
class MyView : UIView {
var top : UIView!
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = UIColor.blueColor()
top = UIView(frame: CGRectMake(0,0, self.frame.width, self.frame.height))
top.backgroundColor = UIColor.yellowColor()
self.addSubview(top)
}
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
let sub = UIView(frame: CGRectMake(0,0, self.frame.width, self.frame.height))
sub.backgroundColor = UIColor.purpleColor()
self.sendSubviewToBack(sub)
UIView.animateWithDuration(1, animations: { () -> Void in
self.top.alpha = 0
}) { (success) -> Void in
println("anim finished")
}
}
}
答案是您无法为实现 drawRect
的视图设置动画 backgroundColor
。我在任何地方都没有看到这方面的文档(如果您知道请发表评论)。
您无法使用 animateWithDuration
或 Core Animation 对其进行动画处理。
This thread 是我找到的最好的解释:
When you implement -drawRect:, the background color of your view is then drawn into the associated CALayer, rather than just being set on the CALayer as a style property... thus prevents you from getting a contents crossfade
正如@Paul 指出的那样,解决方案是在上方、后方或任何地方添加另一个视图,并为其设置动画。这动画效果很好。
希望能很好地理解为什么会这样,以及为什么它会默默地吞下动画而不是大喊大叫。
不确定这是否适合您,但为了使 UIView 的背景颜色动起来,我将其添加到 UIView 扩展中:
extension UIView {
/// Pulsates the color of the view background to white.
///
/// Set the number of times the animation should repeat, or pass
/// in `Float.greatestFiniteMagnitude` to pulsate endlessly.
/// For endless animations, you need to manually remove the animation.
///
/// - Parameter count: The number of times to repeat the animation.
///
func pulsate(withRepeatCount count: Float = 1) {
let pulseAnimation = CABasicAnimation(keyPath: "backgroundColor")
pulseAnimation.fromValue = <#source UIColor#>.cgColor
pulseAnimation.toValue = <#target UIColor#>.cgcolor
pulseAnimation.duration = 0.4
pulseAnimation.autoreverses = true
pulseAnimation.repeatCount = count
pulseAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
self.layer.add(pulseAnimation, forKey: "Pulsate")
CATransaction.commit()
}
}
将其粘贴到 Xcode 中的源文件时,请将占位符替换为您想要的两种颜色。或者您可以将整行替换为以下值:
pulseAnimation.fromValue = backgroundColor?.cgColor
pulseAnimation.toValue = UIColor.white.cgColor
我有一个自定义 UIView,我想为其设置动画 backgroundColor
属性。这是 UIView
的 animatable property。
这是代码:
class ETTimerUIView: UIView {
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
// other methods
func flashBg() {
UIView.animateWithDuration( 1.0, animations: {
self.backgroundColor = UIColor.colorYellow()
})
}
override func drawRect() {
// Something related to a timer I'm rendering
}
这段代码导致动画跳过并且颜色立即改变:
self.backgroundColor = UIColor.colorYellow() // Changes immediately to yellow
如果我对 alpha 进行动画处理,这会按预期在一秒内从 1 到 0 进行动画处理:
self.alpha = 0 // animates
在这种情况下如何为背景颜色变化设置动画?
- Implementing
drawRect
blocks backgroundColor animation,但尚未提供答案。 - Maybe this is why you can't combine
drawRect
andanimateWithDuration
,但我不是很懂
我想我需要创建一个单独的视图——它应该放在同一个视图控制器的故事板中吗?以编程方式创建?
抱歉,我是 iOS 和 Swift 的新手。
当我尝试它时它确实不起作用,我有一个相关的问题,将 layoutIfNeeded() 方法放入动画中工作并使视图平滑动画(move button towards target using constraints, no reaction?)。但是在这种情况下,使用 backgroundColor 是行不通的。如果有人知道答案,我会很想知道。
但如果您现在需要一个解决方案,您可以创建一个仅用作容器的 UIView(以编程方式或通过故事板)。然后在里面添加 2 个视图:一个在上面,一个在下面,与容器具有相同的框架。你只改变顶视图的alpha,让用户看到后面的视图:
class MyView : UIView {
var top : UIView!
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = UIColor.blueColor()
top = UIView(frame: CGRectMake(0,0, self.frame.width, self.frame.height))
top.backgroundColor = UIColor.yellowColor()
self.addSubview(top)
}
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
let sub = UIView(frame: CGRectMake(0,0, self.frame.width, self.frame.height))
sub.backgroundColor = UIColor.purpleColor()
self.sendSubviewToBack(sub)
UIView.animateWithDuration(1, animations: { () -> Void in
self.top.alpha = 0
}) { (success) -> Void in
println("anim finished")
}
}
}
答案是您无法为实现 drawRect
的视图设置动画 backgroundColor
。我在任何地方都没有看到这方面的文档(如果您知道请发表评论)。
您无法使用 animateWithDuration
或 Core Animation 对其进行动画处理。
This thread 是我找到的最好的解释:
When you implement -drawRect:, the background color of your view is then drawn into the associated CALayer, rather than just being set on the CALayer as a style property... thus prevents you from getting a contents crossfade
正如@Paul 指出的那样,解决方案是在上方、后方或任何地方添加另一个视图,并为其设置动画。这动画效果很好。
希望能很好地理解为什么会这样,以及为什么它会默默地吞下动画而不是大喊大叫。
不确定这是否适合您,但为了使 UIView 的背景颜色动起来,我将其添加到 UIView 扩展中:
extension UIView {
/// Pulsates the color of the view background to white.
///
/// Set the number of times the animation should repeat, or pass
/// in `Float.greatestFiniteMagnitude` to pulsate endlessly.
/// For endless animations, you need to manually remove the animation.
///
/// - Parameter count: The number of times to repeat the animation.
///
func pulsate(withRepeatCount count: Float = 1) {
let pulseAnimation = CABasicAnimation(keyPath: "backgroundColor")
pulseAnimation.fromValue = <#source UIColor#>.cgColor
pulseAnimation.toValue = <#target UIColor#>.cgcolor
pulseAnimation.duration = 0.4
pulseAnimation.autoreverses = true
pulseAnimation.repeatCount = count
pulseAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
self.layer.add(pulseAnimation, forKey: "Pulsate")
CATransaction.commit()
}
}
将其粘贴到 Xcode 中的源文件时,请将占位符替换为您想要的两种颜色。或者您可以将整行替换为以下值:
pulseAnimation.fromValue = backgroundColor?.cgColor
pulseAnimation.toValue = UIColor.white.cgColor