[英]Why can't I do any CABasicAnimation or Keyframe animation stuff?
[英]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.