jeudi 13 août 2015

CABasicAnimation responsiveness

I have a custom UIActivityIndicatorView. It is a view, with a CAAnimation on its layer. The problem is the following:

I do some heavy work and create a lot of views. It takes approximately 0.5 seconds. In order for it to be smooth I decided to use activity indicator, while it "happens". It was all fine with default activity indicator, however with the one that I wrote I get unexpected results.

So, when the view loads I launch my activity indicator, which starts animating. When heavy duty work starts my view freezes for 0.5 seconds and when it's done I stop animating it and it disappears. This "freeze" looks very unpleasant to an eye. Because the idea was to keep animating while other views get initialized and added as subviews(although hidden).

I suspect that the problem is that my "activity indicator" is not asynchronous or simply was not coded right.

Here is the code for it:

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

regarding animationDidStop method:

The idea is the following the view pulsates, and after it has shrunk it starts growing again and the background color is changed.

Any idea on what I'm doing wrong ?

Thank You.



via Chebli Mohamed

Aucun commentaire:

Enregistrer un commentaire