选择性地覆盖 CALayer 隐式动画
Posted
技术标签:
【中文标题】选择性地覆盖 CALayer 隐式动画【英文标题】:Selectively overriding CALayer implicit animations 【发布时间】:2011-04-08 00:51:27 【问题描述】:我有一个 CALayer 子类,它被限制为父层的宽度,但高度是固定的。我希望在调整窗口大小时禁用隐式动画,但在设置图层高度时启用。
要在调整窗口大小时禁用动画,我将图层操作设置为
NSMutableDictionary *actions = [[NSMutableDictionary alloc] initWithObjectsAndKeys:[NSNull null], @"bounds", [NSNull null], @"position", nil];
这似乎有效。然后我覆盖了层子类中的 actionForKey: 方法
- (id<CAAction>)actionForKey:(NSString *)event
if ([event isEqualToString:@"frame.size.height"])
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"frame.size.height"];
[animation setDuration:0.5f];
return animation;
return nil;
但是当我改变我的层的高度时
[layer setValue:[NSNumber numberForFloat:50.0] forKey:@"frame.size.height"];
高度改变但没有动画。我看到使用 frame.size.height 调用 actionForKey: 方法,但无论我返回什么,它都不会被动画化。如果我没有设置动作,或者没有 actionForKey: 方法,高度会正确动画,但是窗口大小也会被动画,这是我不想要的。
另外,也许我误解了,但我认为从 actionForKey: 返回 nil 会使默认动画运行,但似乎即使该方法的存在也会停止所有隐式动画(无论操作字典是否设置) .
我在这里缺少什么,我将不胜感激。
【问题讨论】:
【参考方案1】:您的子类将为每个键调用actionForKey:
,因此如果您返回nil
,则不会对该键执行任何操作。如果你想要默认动画,你应该返回[super actionForKey:event]
或[CALayer defaultActionForKey:event]
。
一个层的frame
是从它的bounds
和position
计算出来的,所以如果这两个没有动画,frame
就没有动画。*
你想做的是:
[CATransaction setValue:kCFBooleanTrue
forKey:kCATransactionDisableActions]
当您的图层因窗口大小调整而调整大小时。这将在这次禁用动画(对于此事务);当您直接更改图层的大小时,它仍然会动画。我不确定打那个电话的正确位置是什么;我只是尝试在通知窗口正在调整大小的回调中执行此操作,但这不起作用。我相信你不会很难弄清楚将它放在代码中的什么位置。
*:事实上,文档说:
注意:frame 属性不能直接设置动画。相反,您应该对 bounds、anchorPoint 和 position 属性的适当组合进行动画处理,以获得所需的结果。
【讨论】:
谢谢你,这一切都清楚了。我最终继承了 CAConstraintsLayoutManager 并禁用了 layoutSublayersOfLayer: 方法中的操作。它似乎有效,虽然我不知道这是否是最好的方法。 听起来不错。我让我的观点本身采用CALayoutManager
协议来处理一个相关的、稍微简单的案例。很高兴我能帮上忙。
如果你禁用父层的 layoutSublayers 方法中的操作,它似乎也可以工作。【参考方案2】:
有,正如他们所说.. 给这只猫剥皮的几种方法...我发现其中一种最容易...通过在图层的“动作”字典中设置一些条目。 .
CALayer *stopAnimatingLikeThat = CALayer.new;
stopAnimatingLikeThat.actions =
@ @"position":NSNull.null, @"bounds":NSNull.null ;
这将阻止边界变化等烦人的“卡在蜂蜜中”“隐式动画”等。
【讨论】:
这是一个很好的方法,因为您可以将 CALayer 设置为在初始化时不调整位置和边界的大小。 在没有隐式动画的图层中重绘文本yourLayer.actions = @ @"contents":NSNull.null ;
以上是关于选择性地覆盖 CALayer 隐式动画的主要内容,如果未能解决你的问题,请参考以下文章
通过 AVExportSession 导出带有隐式动画的 CALayer
在 -[CALayer setNeedsDisplayInRect:] 中禁用隐式动画