观察动画期间UIView的帧变化

sam*_*ous 11 animation uiview ios observer-pattern

我想观察UIView原点的x坐标在使用动画时的变化animateWithDuration:delay:options:animations:completion:.我想在粒度级别跟踪此动画期间x坐标的变化,因为我想在交互中更改另一个视图,即动画视图可能与之接触.我想在确切的联系点做出改变.我想了解在更高层次上做这样的事情的最佳方法:

- 我应该animateWithDuration:...在联系点的完成回电中使用吗?换句话说,第一个动画一直运行直到它到达那个x坐标,其余的动画发生在完成回调中?

- 我应该使用NSNotification观察者并观察框架属性的变化吗?这有多准确/精细?我可以跟踪x的每个变化吗?我应该在一个单独的线程中这样做吗?

欢迎任何其他建议.我正在寻找一个很好的练习.

fun*_*ct7 14

使用,CADisplayLink因为它是专门为此目的而构建的.在文档中,它说:

一旦显示链接与运行循环相关联,当需要更新屏幕内容时,将调用目标上的选择器.

对我来说,我有一个填满的酒吧,当它通过一定的标记时,我不得不改变那个标记上方的视图的颜色.

这就是我做的:

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).")
    }
}
Run Code Online (Sandbox Code Playgroud)

在示例中,我将frameInterval属性设置为,3因为我不必严格更新.默认值是1,它意味着它将为每一帧触发,但它会对性能产生影响.


san*_*thu 8

NSTimer在每次失效后创建一个延迟并运行特定选择器.
在该方法中,检查动画视图的框架并将其与碰撞视图进行比较.

并确保使用presentationLayer框架, 因为如果在动画时访问view.frame,它会给出在动画中不变的目标框架.

CGRect animationViewFrame= [[animationView.layer presentationLayer] frame];
Run Code Online (Sandbox Code Playgroud)

如果你不想创建计时器,write a selector which calls itself after some delay.延迟大约.01秒.

澄清 - >
假设您有一个视图,您可以将其位置从(0,0)设置为(100,100),持续时间为5秒.假设您将KVO实现到此视图的框架

当您调用时animateWithDuration block,视图的位置会直接更改为(100,100),这是最终值,即使视图以中间位置值移动也是如此.

因此,您的KVO将在动画开始的瞬间被解雇一次.因为,图层有layer TreePresentation Tree.虽然layer tree只存储目的地值而presentation Layer存储中间值.
当您访问view.frame它时,它将始终给出帧的值而layer tree不是它所采用的中间帧.

所以,你必须presentation Layer frame用来获得中间帧.

希望这可以帮助.