2014-03-02 54 views
1

我爲CABasicAnimation實例的緊湊創建制作了一個包裝。 它通過一個名爲change:from:to:in:ease:delay:done:的實例方法通過UIView類別實現。因此,例如,我可以這樣做:當我在animationDidStart中設置最終值時,CABasicAnimation沒有插值:

[self.logo 
    change:@"y" 
    from:nil   // Use current self.logo.layer.position.y 
    to:@80 
    in:1    // Finish in 1000 ms 
    ease:@"easeOutQuad" // A selector for a CAMediaTimingFunction category method 
    delay:0 
    done:nil]; 

問題

當CABasicAnimation開始,animationDidStart:手柄設置self.logo.layer.position.y 80(終值)。在它像這樣工作之前,我嘗試使用animationDidStop:finished:來做同樣的事情,但在完成動畫後發現圖層閃爍。 現在,該圖層直接到達最終值,並且不會發生插值。我在我UIView類實現animationDidStart:像這樣:

- (void)animationDidStart:(CAAnimation *)animation 
{ 
    [self.layer 
     setValue:[animation valueForKey:@"toValue"] 
     forKeyPath:[animation valueForKey:@"keyPath"]]; 
} 

我爲了配合表現層模型層(換句話說,以防止重新回到起始位置)設定值的終點。

這裏的實施change:from:to:in:ease:delay:done: ...

- (CABasicAnimation*) change:(NSString*)propertyPath 
         from:(id)from 
          to:(id)to 
          in:(CGFloat)seconds 
         ease:(NSString*)easeName 
         delay:(CGFloat)delay 
         done:(OnDoneCallback)done 
{ 
    NSString* keyPath = [app.CALayerAnimationKeyPaths objectForKey:propertyPath]; 
    if (keyPath == nil) keyPath = propertyPath; 
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:keyPath]; 
    if (delay > 0) animation.beginTime = CACurrentMediaTime() + delay; 
    if (easeName != nil) animation.timingFunction = [CAMediaTimingFunction performSelector:NSSelectorFromString(easeName)]; 
    if (from != nil) animation.fromValue = from; 
    animation.toValue = to; 
    animation.duration = seconds; 
    animation.delegate = self; 
    [self.layer setValue:done forKey:@"onDone"]; 
    [self.layer addAnimation:animation forKey:keyPath]; 
    return animation; 
} 

在上面的代碼中的第一行,這是我的NSDictionary使用屬性的快捷方式轉換爲真正的keyPath。這樣我就可以每次輸入@"y"而不是@"position.y"

app.CALayerAnimationKeyPaths = @{ 
    @"scale": @"transform.scale", 
    @"y": @"position.y", 
    @"x": @"position.x", 
    @"width": @"frame.size.width", 
    @"height": @"frame.size.height", 
    @"alpha": @"opacity", 
    @"rotate": @"transform.rotation" 
}; 

還有問題嗎?

回答

2

你看到的是,我認爲,預期的行爲。在該屬性動畫開始後,您正在設置一個動畫屬性。實際上,這是最常見和推薦的方式,可以完成您所看到的事情,即取消動畫並立即跳至最終位置。所以你會刻意取消你自己的動畫。

如果這不是你想要的,不要這樣做。只需將動畫屬性設置爲其最終值,然後將動畫附加到圖層上 - 當然,請謹慎操作,以免觸發隱式動畫。

+0

所以你說我應該把'[self.layer setValue:forKeyPath:keyPath];''在'[self.layer addAnimation:animation forKey:keyPath]之前';'? – aleclarson

+1

請參閱我的書,以建立CABasicAnimation的規範方式以及爲什麼它按照以下方式工作:http://www.apeth.com/iOSBook/ch17.html#_using_a_cabasicanimation – matt

+1

不需要在_right_之前。無論如何,直到運行循環結束,纔會發生任何事情。可能是你在你的方法中做的第一件事。事實上,它更簡單,因爲這樣你就可以建立模型層和表示層,並且不需要設置from值和value值。 – matt