簡體   English   中英

為什么我不能在CABasicAnimation完成后設置圖層的不透明度?

[英]Why can't I set the opacity of a layer after a CABasicAnimation finished?

我有一個名為specialLayer的子specialLayer 不透明度的隱式動畫被禁用,如下所示:

self.specialLayer.actions = [NSDictionary dictionaryWithObjectsAndKeys:
                                            [NSNull null], @"opacity", nil];

訪問此子圖層的方法只有兩種。

- (void)touchDown {
    self.specialLayer.opacity = 0.25f;
}

- (void)touchUp {
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
    animation.fromValue = [NSNumber numberWithFloat:self.specialLayer.opacity];
    animation.toValue = [NSNumber numberWithFloat:1.0];
    animation.duration = 0.5;
    animation.removedOnCompletion = NO;
    animation.fillMode = kCAFillModeForwards;
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
    [self.specialLayer addAnimation:animation forKey:@"opacity"];
}

有時候是這樣的:

1)用戶按下按鈕(保持)並調用-touchDown。 specialLayer的不透明度立即變為0.25

2)用戶釋放按鈕和-touchUp被調用。 specialLayer的不透明度可以恢復為1.0

此序列僅適用於ONCE!

3)用戶再次按下按鈕(按住)並調用-touchDown。 但specialLayer的不透明度在屏幕上不會改變! 即使self.specialLayer.opacity = 0.25f;也沒有任何self.specialLayer.opacity = 0.25f; 被叫。 不透明度似乎仍為1.0f。

4)用戶抬起手指並調用-touchUp。 specialLayer的不透明度為0.25,從那里動畫到1.0f。

我檢查了NSLog以確保按此順序調用方法。 他們是這樣。

當我取消注釋動畫代碼並將不透明度直接設置為1.0時,后續的直接不透明度更改立即生效。 絕對是導致問題的CABasicAnimation。 刪除禁用隱式動畫的代碼對此問題沒有影響。

我不能為我的生活弄清楚這里發生了什么。 為什么在我為不透明度添加CABasicAnimation之后的一段時間后,CALayer沒有反映我設置的不透明度值? 這是一個錯誤嗎?

我究竟做錯了什么?

您將動畫的removedOnCompletion設置為NO 這意味着當動畫完成時,它仍然保留在圖層上,並且仍然可以控制opacity的值以進行渲染。 當您第二次調用此代碼時,新動畫將替換舊動畫,這會導致跳轉(因為它現在使用新設置的0.25f作為起點)。

解決方案是停止將removedOnCompletion設置為NO 相反,您應該在添加動畫的同時,將圖層的實際不透明度設置為與動畫端點相同的值。

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
// you can omit fromValue since you're setting it to the layer's opacity
// by omitting fromValue, it uses the current value instead. Just remember
// to not change layer.opacity until after you add the animation to the layer
animation.toValue = [NSNumber numberWithFloat:1];
animation.duration = 0.5;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
[layer addAnimation:animation forKey:@"opacity"];
layer.opacity = 1; // or layer.opacity = [animation.toValue floatValue];

這是因為圖層渲染的工作方式。 當CoreAnimation將圖層樹渲染到屏幕時,它會復制模型樹並生成所謂的表示樹。 它通過復制所有圖層,然后應用所有動畫來完成此操作。 因此,它會遍歷圖層上的每個動畫,將時間插入計時功能,將生成的進度插入到from / to值之間的插值中,並將該最終值應用回表示層的屬性。

因此,當您永久地在圖層上留下動畫時,此動畫將始終覆蓋該鍵的實際模型值。 更改layer.opacity次數layer.opacity ,控制opacity的動畫將始終覆蓋該值以用於演示目的。

同樣的原因也是為什么你可以在添加動畫后將layer.opacity設置為你想要的任何東西,因為動畫將優先。 僅當移除動畫時(默認情況下在動畫完成時才會發生),將再次使用該屬性的模型值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM