Ben*_*ieb 133 iphone core-animation calayer ios
我的-drawInContext:方法中有一个包含一些复杂绘图代码的图层.我正在尝试最小化我需要做的绘图量,所以我使用-setNeedsDisplayInRect:仅更新已更改的部分.这是非常好的工作.但是,当图形系统更新我的图层时,它会使用交叉淡入淡出从旧图像过渡到新图像.我希望它能立即切换.
我已经尝试使用CATransaction来关闭操作并将持续时间设置为零,并且都不起作用.这是我正在使用的代码:
[CATransaction begin];
[CATransaction setDisableActions: YES];
[self setNeedsDisplayInRect: rect];
[CATransaction commit];
Run Code Online (Sandbox Code Playgroud)
我应该使用不同的CATransaction方法(我也尝试过-setValue:forKey:使用kCATransactionDisableActions,结果相同).
Bra*_*son 168
您可以通过将图层上的操作字典设置[NSNull null]为作为相应键的动画返回来执行此操作.例如,我用
NSDictionary *newActions = @{
@"onOrderIn": [NSNull null],
@"onOrderOut": [NSNull null],
@"sublayers": [NSNull null],
@"contents": [NSNull null],
@"bounds": [NSNull null]
};
layer.actions = newActions;
Run Code Online (Sandbox Code Playgroud)
在我的一个图层中插入或更改子图层时禁用淡入/淡出动画,以及图层大小和内容的更改.我相信contents关键是你正在寻找的关键是为了防止更新图纸上的交叉淡入淡出.
Swift版本:
let newActions = [
"onOrderIn": NSNull(),
"onOrderOut": NSNull(),
"sublayers": NSNull(),
"contents": NSNull(),
"bounds": NSNull(),
]
Run Code Online (Sandbox Code Playgroud)
mxc*_*xcl 90
也:
[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
//foo
[CATransaction commit];
Run Code Online (Sandbox Code Playgroud)
use*_*170 31
更改图层的属性时,CA通常会创建一个隐式事务对象来为更改设置动画.如果您不想为更改设置动画,可以通过创建显式事务并将其kCATransactionDisableActions属性设置为true来禁用隐式动画.
Objective-C的
[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
// change properties here without animation
[CATransaction commit];
Run Code Online (Sandbox Code Playgroud)
迅速
CATransaction.begin()
CATransaction.setValue(kCFBooleanTrue, forKey: kCATransactionDisableActions)
// change properties here without animation
CATransaction.commit()
Run Code Online (Sandbox Code Playgroud)
sko*_*zin 23
除了Brad Larson的回答:对于自定义图层(由您创建),您可以使用委托而不是修改图层的actions字典.这种方法更具动态性,可能更具性能.它允许禁用所有隐式动画,而无需列出所有可设置动画的键.
不幸的是,不可能将UIViews用作自定义层委托,因为每个UIView委托都已经是自己层的委托.但你可以使用这样一个简单的助手类:
@interface MyLayerDelegate : NSObject
@property (nonatomic, assign) BOOL disableImplicitAnimations;
@end
@implementation MyLayerDelegate
- (id<CAAction>)actionForLayer:(CALayer *)layer forKey:(NSString *)event
{
if (self.disableImplicitAnimations)
return (id)[NSNull null]; // disable all implicit animations
else return nil; // allow implicit animations
// you can also test specific key names; for example, to disable bounds animation:
// if ([event isEqualToString:@"bounds"]) return (id)[NSNull null];
}
@end
Run Code Online (Sandbox Code Playgroud)
用法(在视图内):
MyLayerDelegate *delegate = [[MyLayerDelegate alloc] init];
// assign to a strong property, because CALayer's "delegate" property is weak
self.myLayerDelegate = delegate;
self.myLayer = [CALayer layer];
self.myLayer.delegate = delegate;
// ...
self.myLayerDelegate.disableImplicitAnimations = YES;
self.myLayer.position = (CGPoint){.x = 10, .y = 42}; // will not animate
// ...
self.myLayerDelegate.disableImplicitAnimations = NO;
self.myLayer.position = (CGPoint){.x = 0, .y = 0}; // will animate
Run Code Online (Sandbox Code Playgroud)
有时将视图的控制器作为视图的自定义子层的委托是很方便的; 在这种情况下,不需要辅助类,您可以actionForLayer:forKey:在控制器内部实现方法.
重要提示:不要尝试修改UIView底层的委托(例如启用隐式动画) - 会发生不好的事情:)
注意:如果你想要动画(不要禁用动画)图层重绘,将[CALayer setNeedsDisplayInRect:]调用放在一个内部是没用的CATransaction,因为实际的重绘可能(有时可能会)稍后发生.好的方法是使用自定义属性,如本答案中所述.
这是一个更有效的解决方案,类似于接受的答案,但对于Swift.对于某些情况,每次修改一个性能问题的值时,它会比创建一个事务更好,正如其他人提到的那样,例如以60fps左右拖动图层位置的常见用例.
// Disable implicit position animation.
layer.actions = ["position": NSNull()]
Run Code Online (Sandbox Code Playgroud)
有关如何解析图层操作的信息,请参阅Apple的文档.实现委托会跳过级联中的另一个级别,但在我的情况下由于需要设置为关联的UIView的委托的警告而太乱了.
编辑:更新了感谢指出NSNull符合的评论者CAAction.
实际上,我没有找到任何合适的答案.解决这个问题的方法是这样的:
- (id<CAAction>)actionForKey:(NSString *)event {
return nil;
}
Run Code Online (Sandbox Code Playgroud)
然后你可以使用它中的任何逻辑来禁用特定的动画,但是因为我想要将它们全部删除,所以我返回了nil.
根据Sam的回答和Simon的困难...在创建CSShapeLayer后添加委托引用:
CAShapeLayer *myLayer = [CAShapeLayer layer];
myLayer.delegate = self; // <- set delegate here, it's magic.
Run Code Online (Sandbox Code Playgroud)
......"m"文件中的其他地方......
基本上与Sam没有通过自定义"disableImplicitAnimations"变量排列切换的能力相同.更多的是"硬线"方法.
- (id<CAAction>)actionForLayer:(CALayer *)layer forKey:(NSString *)event {
// disable all implicit animations
return (id)[NSNull null];
// allow implicit animations
// return nil;
// you can also test specific key names; for example, to disable bounds animation:
// if ([event isEqualToString:@"bounds"]) return (id)[NSNull null];
}
Run Code Online (Sandbox Code Playgroud)
小智 6
在 Swift 中禁用隐式图层动画
CATransaction.setDisableActions(true)
Run Code Online (Sandbox Code Playgroud)
找到了一个更简单的方法来禁用内动作CATransaction在内部调用setValue:forKey:的kCATransactionDisableActions关键:
[CATransaction setDisableActions:YES];
Run Code Online (Sandbox Code Playgroud)
迅速:
CATransaction.setDisableActions(true)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
47094 次 |
| 最近记录: |