如何禁用 CALayer 隐式动画?
这让我发疯!我正在开发一个绘图应用程序。假设我正在开发一个名为sheet的UIView
。
我向此视图添加一些子图层 ([sheet.layer addSublayer:...]
),然后我想绘制到其中。为此,我创建一个 CGImageRef 并将其放入图层的内容中。但它是动画的,我不想要那样。
我尝试了一切:
removeAnimationForKey:
removeAllAnimations
- 设置动作字典
- 使用动作层
delegate
[CATransaction setDisableAnimations:YES]
它是似乎是正确的。我不明白为什么这一层仍然是动画的;_;
我做错了什么吗?有什么秘密方法吗?
It's driving me crazy! I am working on a drawing application. Let's say I am working on a UIView
called sheet.
I am adding some sublayers to this view ([sheet.layer addSublayer:...]
) and then I want to draw into them. To do so I am creating a CGImageRef
and putting it into the layer's contents
. But it's animated and I don't want that.
I tried everything:
removeAnimationForKey:
removeAllAnimations
- set the actions dictionary
- using the actionlayer
delegate
[CATransaction setDisableAnimations:YES]
It's seems correct. I don't understand why this layer is still animated ;_;
Am I doing something wrong? Is there a secret way?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(12)
斯威夫特
Swift
您必须通过将代码包装在 CATransaction 中来显式禁用动画
You have to explicitly disable animations by wrapping your code in a CATransaction
另一种方法:
您应该禁用sheet.layer的默认动画,它在添加子层时隐式调用。
您还应该为每个子层添加内容动画。当然,您可以在每次设置sublayer.content时使用CATransaction的“kCATransactionDisableActions”。但是,当您创建子层时,您可以禁用此动画一次。
这是代码:
Another way:
You should disable default animation of your sheet.layer, which is called implicitly when adding sublayer.
You should also content-animation of each sublayer. Of course, you can use "kCATransactionDisableActions" of CATransaction each time you set sublayer.content. But, you can disable this animation once, when you are creating your sublayer.
Here is code:
从 Mac OS X 10.6 和 iOS 3 开始,
CATransaction
还具有一个setDisableActions
方法,用于设置键kCATransactionDisableActions
的值。在 Swift 中,我喜欢使用这个扩展方法:
然后你可以像这样使用它:
As of Mac OS X 10.6 and iOS 3,
CATransaction
also has asetDisableActions
method that sets the value for keykCATransactionDisableActions
.In Swift, I like to use this extension method:
You can then use it like this:
Swift 4 扩展:
用法:
Swift 4 extension :
Usage :
层扩展:
用法:
Layer extension:
Usage:
这是一个老问题,但问题仍然存在。有时您不想要 CALayer 强加给您的动画。我对基于事务的方法不满意,因为我只想关闭这些操作。为了好的。这是一个子类 CALayer 的 Swift 4 解决方案,允许选择是允许任何操作还是全局禁用它们。您还可以创建具有相同内容的 CAShapeLayer、CATextLayer 子类:
This is an old question but the problem remains. Sometimes you don't want the animations that CALayer forces on you. I wasn't happy with the transaction based approach as I just wanted to turn these actions off. For good. Here's a Swift 4 solution to subclass CALayer to allow a choice whether to allow any action or globally disable them. You can also create CAShapeLayer, CATextLayer subclasses with the same contents:
Swift 2
我能够禁用所有动画,如下所示,其中
myView
是您正在使用的视图:作为旁注,删除所有图层:
Swift 2
I was able to disable all animations as follows, where
myView
is the view you are working with:And as a side note, removing all layers:
可重用的全局代码:
将此代码添加到代码中的任何位置(全局范围)
Reusable global code:
Add this code anywhere in your code (Globally scoped)
以下解决方案避免在层之前和之后临时使用 +(CATransaction) 并永久设置所需的行为(CALayers 的特定属性没有动画),除非您有意创建操作。这样,您最终会得到更清晰的源代码,清楚地表达该方法是什么,并且仍然拥有 CATransaction 的全部潜在能力。
在使用 ie
[self.layer addSublayer:yourCALayer]
将图层添加到视图之前以及在添加图层之后,您可以通过覆盖动画来禁用 CALayer 的特定动画属性钥匙。您设置为 NULL 的键以该属性命名,此处显示的内容类似于对layer.position = CGPoint(x,y);
所做的操作,因为
actions
属性是一个NSDictionary 不允许存储nil
,您可以使用[NSNull null]
将其显式设置为 NULL 对象,这与(id)kCFNull
相同代码>您可以通过迭代视图层的所有子层来对所有子层执行此操作...
The following solution avoids temporarily use of +(CATransaction) before and after layers and sets the needed behaviour (no animation for specific properties of CALayers) permanently unless you create actions on purpose. This way you end up with cleaner source clearly expressing what the approach is and still have the full potential power of CATransaction.
before adding the layer to your view with i.e.
[self.layer addSublayer:yourCALayer]
and also after its already added you can disable specific animated propertys of your CALayer by overwriting the animation key. The key you set to NULL is named after the property, here shown like its done for thelayer.position = CGPoint(x,y);
Because the
actions
property is an NSDictionary which does not allow storing ofnil
you set it explicit to an NULL object with[NSNull null]
, which is the same as(id)kCFNull
You can do this for all sublayers by iterating thru all sublayers of the views layer with...
我完全同意瑞安的观点。他的答案是针对 MacOS,对于 iOS,您添加以下内容来创建 NSNull() 操作。这个问题 Disabling隐式动画 -[CALayer setNeedsDisplayInRect:] 和文档标题引导我到这里
I completely agree with Ryan. His answer is for MacOS, for iOS you add the following to create an NSNull() action. This question Disabling implicit animations in -[CALayer setNeedsDisplayInRect:] and the documentation in the header lead me here
在 2011 年,使用 CATransaction 是有意义的,但从 iOS 7 (2013) 开始,您应该使用
+[UIView PerformWithoutAnimation:]
。这可以确保您不会留下未提交的 CATransaction,以防return
语句滑入begin
和commit
之间的代码中。对于某些系统视图,某些更改仅发生在布局上(例如设置
UIButton
的标题时)。在这些视图上调用layoutIfNeeded
。目标 C:
Swift:
In 2011 it made sense to use
CATransaction
, but since iOS 7 (2013) you should use+[UIView performWithoutAnimation:]
. That makes sure you are not left with an uncommitted CATransaction in case areturn
statement slips in the code betweenbegin
andcommit
.For some system views, some changes only happen on layout (like when setting the title of a
UIButton
). CalllayoutIfNeeded
on those views.Objective C:
Swift: