CABasicAnimation 响应能力
CABasicAnimation responsiveness
我有一个自定义的 UIActivityIndicatorView。它是一个视图,在其层上有一个 CAAnimation。问题如下:
我做了一些繁重的工作并创建了很多视图。大约需要 0.5 秒。为了让它顺利,我决定使用 activity 指标,而它 "happens"。使用默认的 activity 指标一切都很好,但是使用我写的指标却得到了意想不到的结果。
因此,当视图加载时,我启动 activity 指示器,它开始动画。当繁重的工作开始时,我的视图会冻结 0.5 秒,完成后我会停止动画并消失。这个"freeze"看着很不顺眼。因为这个想法是在其他视图被初始化并添加为子视图(尽管隐藏)时保持动画。
我怀疑问题是我的 "activity indicator" 不是异步的,或者只是编码不正确。
这是它的代码:
class CustomActivityIndicatorView: UIView {
// MARK - Variables
var colors = [UIColor.greenColor(),UIColor.grayColor(),UIColor.blueColor(),UIColor.redColor()]
var colorIndex = 0
var animation: CABasicAnimation!
lazy var customView : UIView! = {
let frame : CGRect = CGRectMake(0.0, 0.0, 100, 100)
let view = UIView(frame: frame)
image.frame = frame
image.center = view.center
view.backgroundColor = UIColor.greenColor()
view.clipsToBounds = true
view.layer.cornerRadius = frame.width/2
return view
}()
var isAnimating : Bool = false
var hidesWhenStopped : Bool = true
var from: NSNumber = 1.0
var to: NSNumber = 0.0
var growing = false
override func animationDidStart(anim: CAAnimation!) {
}
override func animationDidStop(anim: CAAnimation!, finished flag: Bool) {
growing = !growing
if growing {
colorIndex++
if colorIndex == colors.count {
colorIndex = 0
}
println(colorIndex)
customView.backgroundColor = colors[colorIndex]
from = 0.0
to = 1.0
} else {
from = 1.0
to = 0.0
}
if isAnimating {
addPulsing()
resume()
}
}
// MARK - Init
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.addSubview(customView)
addPulsing()
pause()
self.hidden = true
}
// MARK - Func
func addPulsing() {
let pulsing : CABasicAnimation = CABasicAnimation(keyPath: "transform.scale")
pulsing.duration = 0.4
pulsing.removedOnCompletion = false
pulsing.fillMode = kCAFillModeForwards
pulsing.fromValue = from
pulsing.toValue = to
pulsing.delegate = self
let layer = customView.layer
layer.addAnimation(pulsing, forKey: "pulsing")
}
func pause() {
let layer = customView.layer
let pausedTime = layer.convertTime(CACurrentMediaTime(), fromLayer: nil)
layer.speed = 0.0
layer.timeOffset = pausedTime
isAnimating = false
}
func resume() {
let layer = customView.layer
let pausedTime : CFTimeInterval = layer.timeOffset
layer.speed = 1.0
layer.timeOffset = 0.0
layer.beginTime = 0.0
let timeSincePause = layer.convertTime(CACurrentMediaTime(), fromLayer: nil) - pausedTime
layer.beginTime = timeSincePause
isAnimating = true
}
func startAnimating () {
if isAnimating {
return
}
if hidesWhenStopped {
self.hidden = false
}
resume()
}
func stopAnimating () {
let layer = customView.layer
if hidesWhenStopped {
self.hidden = true
}
pause()
layer.removeAllAnimations()
}
deinit {
println("Spinner Deinitied")
}
}
关于 animationDidStop 方法:
思路如下。视图跳动,缩小后又开始变大,背景颜色也变了。
知道我做错了什么吗?
使用CAKeyFrameAnimation解决,达到同样的效果。对于遇到同样问题的每个人,请记住 animationDidStart 和 animationDidStop 在主线程上启动 运行,这样无论您对动画做什么,如果主线程繁忙,都会停止。
我有一个自定义的 UIActivityIndicatorView。它是一个视图,在其层上有一个 CAAnimation。问题如下:
我做了一些繁重的工作并创建了很多视图。大约需要 0.5 秒。为了让它顺利,我决定使用 activity 指标,而它 "happens"。使用默认的 activity 指标一切都很好,但是使用我写的指标却得到了意想不到的结果。
因此,当视图加载时,我启动 activity 指示器,它开始动画。当繁重的工作开始时,我的视图会冻结 0.5 秒,完成后我会停止动画并消失。这个"freeze"看着很不顺眼。因为这个想法是在其他视图被初始化并添加为子视图(尽管隐藏)时保持动画。
我怀疑问题是我的 "activity indicator" 不是异步的,或者只是编码不正确。
这是它的代码:
class CustomActivityIndicatorView: UIView {
// MARK - Variables
var colors = [UIColor.greenColor(),UIColor.grayColor(),UIColor.blueColor(),UIColor.redColor()]
var colorIndex = 0
var animation: CABasicAnimation!
lazy var customView : UIView! = {
let frame : CGRect = CGRectMake(0.0, 0.0, 100, 100)
let view = UIView(frame: frame)
image.frame = frame
image.center = view.center
view.backgroundColor = UIColor.greenColor()
view.clipsToBounds = true
view.layer.cornerRadius = frame.width/2
return view
}()
var isAnimating : Bool = false
var hidesWhenStopped : Bool = true
var from: NSNumber = 1.0
var to: NSNumber = 0.0
var growing = false
override func animationDidStart(anim: CAAnimation!) {
}
override func animationDidStop(anim: CAAnimation!, finished flag: Bool) {
growing = !growing
if growing {
colorIndex++
if colorIndex == colors.count {
colorIndex = 0
}
println(colorIndex)
customView.backgroundColor = colors[colorIndex]
from = 0.0
to = 1.0
} else {
from = 1.0
to = 0.0
}
if isAnimating {
addPulsing()
resume()
}
}
// MARK - Init
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.addSubview(customView)
addPulsing()
pause()
self.hidden = true
}
// MARK - Func
func addPulsing() {
let pulsing : CABasicAnimation = CABasicAnimation(keyPath: "transform.scale")
pulsing.duration = 0.4
pulsing.removedOnCompletion = false
pulsing.fillMode = kCAFillModeForwards
pulsing.fromValue = from
pulsing.toValue = to
pulsing.delegate = self
let layer = customView.layer
layer.addAnimation(pulsing, forKey: "pulsing")
}
func pause() {
let layer = customView.layer
let pausedTime = layer.convertTime(CACurrentMediaTime(), fromLayer: nil)
layer.speed = 0.0
layer.timeOffset = pausedTime
isAnimating = false
}
func resume() {
let layer = customView.layer
let pausedTime : CFTimeInterval = layer.timeOffset
layer.speed = 1.0
layer.timeOffset = 0.0
layer.beginTime = 0.0
let timeSincePause = layer.convertTime(CACurrentMediaTime(), fromLayer: nil) - pausedTime
layer.beginTime = timeSincePause
isAnimating = true
}
func startAnimating () {
if isAnimating {
return
}
if hidesWhenStopped {
self.hidden = false
}
resume()
}
func stopAnimating () {
let layer = customView.layer
if hidesWhenStopped {
self.hidden = true
}
pause()
layer.removeAllAnimations()
}
deinit {
println("Spinner Deinitied")
}
}
关于 animationDidStop 方法:
思路如下。视图跳动,缩小后又开始变大,背景颜色也变了。
知道我做错了什么吗?
使用CAKeyFrameAnimation解决,达到同样的效果。对于遇到同样问题的每个人,请记住 animationDidStart 和 animationDidStop 在主线程上启动 运行,这样无论您对动画做什么,如果主线程繁忙,都会停止。