Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
556 views
in Technique[技术] by (71.8m points)

ios - Observing change in frame of a UIView during animation

I want to observe changes to the x coordinate of my UIView's origin while it is being animated using animateWithDuration:delay:options:animations:completion:. I want to track changes in the x coordinate during this animation at a granular level because I want to make a change in interaction to another view that the view being animated may make contact with. I want to make that change at the exact point of contact. I want to understand the best way to do something like this at a higher level:

-- Should I use animateWithDuration:... in the completion call back at the point of contact? In other words, The first animation runs until it hits that x coordinate, and the rest of the animation takes place in the completion callback?

-- Should I use NSNotification observers and observe changes to the frame property? How accurate / granular is this? Can I track every change to x? Should I do this in a separate thread?

Any other suggestions would be welcome. I'm looking for a abest practice.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Use CADisplayLink since it is specifically built for this purpose. In the documentation, it says:

Once the display link is associated with a run loop, the selector on the target is called when the screen’s contents need to be updated.

For me I had a bar that fills up, and as it passed a certain mark, I had to change the colors of the view above that mark.

This is what I did:

let displayLink = CADisplayLink(target: self, selector: #selector(animationDidUpdate))
displayLink.frameInterval = 3
displayLink.addToRunLoop(NSRunLoop.mainRunLoop(), forMode: NSDefaultRunLoopMode)

UIView.animateWithDuration(1.2, delay: 0.0, options: [.CurveEaseInOut], animations: { 
    self.viewGaugeGraph.frame.size.width = self.graphWidth
    self.imageViewGraphCoin.center.x = self.graphWidth
    }, completion: { (_) in
        displayLink.invalidate()
})

func animationDidUpdate(displayLink: CADisplayLink) {
    let presentationLayer = self.viewGaugeGraph.layer.presentationLayer() as! CALayer

    let newWidth = presentationLayer.bounds.width

    switch newWidth {
    case 0 ..< width * 0.3: 
        break
    case width * 0.3 ..< width * 0.6: 
        // Color first mark
        break 
    case width * 0.6 ..< width * 0.9:
        // Color second mark
        break
    case width * 0.9 ... width:
        // Color third mark
        break
    default:
        fatalError("Invalid value observed. (newWidth) cannot be bigger than (width).")
    }
}

In the example, I set the frameInterval property to 3 since I didn't have to rigorously update. Default is 1 and it means it will fire for every frame, but it will take a toll on performance.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...