我正在尝试为自定义UIView的边界设置动画,同时保持其图层与其父视图的大小相同。为此,我试图在其父视图旁边设置图层边界的动画。我需要图层来调用drawLayer:withContext AS它的动画,所以我的自定义绘图将正确地改变大小和边界。
正确调用drawLayer并在开始动画之前正确绘制。但我不能让图层在边界动画的每一步调用它的drawLayer方法。相反,它只是将其称为ONCE,立即跳到动画最后一帧的“结束边界”。
// self.bg is a property pointing to my custom UIView
self.bg.layer.needsDisplayOnBoundsChange = YES;
self.bg.layer.mask.needsDisplayOnBoundsChange = YES;
[UIView animateWithDuration:2 delay:0 options:UIViewAnimationOptionCurveEaseOut|UIViewAnimationOptionAutoreverse|UIViewAnimationOptionRepeat animations:^{
[CATransaction begin];
self.bg.layer.bounds = bounds;
self.bg.layer.mask.bounds = bounds;
[CATransaction commit];
self.bg.bounds = bounds;
} completion:nil];
为什么边界不会报告其动画的变化(而不仅仅是最终帧)?我做错了什么?
答案 0 :(得分:3)
这可能会有所帮助,也可能没有帮助......
许多人都不知道Core Animation有一个supercool功能,允许您以可以设置动画的方式定义自己的图层属性。我使用的一个例子是给CALayer子类一个thickness
属性。当我使用Core Animation制作动画时......
CABasicAnimation* ba = [CABasicAnimation animationWithKeyPath:@"thickness"];
ba.toValue = @10.0f;
ba.autoreverses = YES;
[lay addAnimation:ba forKey:nil];
...效果是在整个动画中重复调用drawInContext:
或drawLayer:...
,允许我按照当前thickness属性值(动画过程中的中间值)。
在我看来,可能就是你所追求的那种东西。如果是这样,您可以在此处找到可下载的示例:
讨论(来自我的书):
http://www.apeth.com/iOSBook/ch17.html#_making_a_property_animatable
答案 1 :(得分:1)
这是因为您要绘制的图层与屏幕上显示的图层不同。
当您为图层属性设置动画时,它将立即设置为模型图层中的最终值(正如您所注意到的),并且实际动画在表示层中完成。
您可以访问表示层并查看动画属性的实际值:
CALayer *presentationLayer = (CALayer *)[self.bg.layer presentationLayer];
...
由于您尚未提供drawLayer:withContext
方法,因此不清楚您希望在动画期间绘制什么内容,但如果您想为自定义属性设置动画,请here is a good tutorial执行此操作。
答案 2 :(得分:1)
首先,图层支持(或托管)视图的图层始终调整大小以适合其父视图的边界。如果将视图设置为图层委托,则视图将在每个帧接收drawLayer:inContext:。当然,您必须确保如果您的图层有needsDisplayOnBoundsChange == YES
。
以下是调整窗口大小的示例(在Mac上),然后更改底层的路径。
// My Nib contains one view and one button.
// The view has a MPView class and the button action is resizeWindow:
@interface MPView() {
CAShapeLayer *_hostLayer;
CALayer *_outerLayer;
CAShapeLayer *_innerLayer;
}
@end
@implementation MPView
- (void)awakeFromNib
{
[CATransaction begin];
[CATransaction setDisableActions:YES];
_hostLayer = [CAShapeLayer layer];
_hostLayer.backgroundColor = [NSColor blackColor].CGColor;
_hostLayer.borderColor = [NSColor redColor].CGColor;
_hostLayer.borderWidth = 2;
_hostLayer.needsDisplayOnBoundsChange = YES;
_hostLayer.delegate = self;
_hostLayer.lineWidth = 4;
_hostLayer.strokeColor = [NSColor greenColor].CGColor;
_hostLayer.needsDisplayOnBoundsChange = YES;
self.layer = _hostLayer;
self.wantsLayer = YES;
[CATransaction commit];
[self.window setFrame:CGRectMake(100, 100, 200, 200) display:YES animate:NO];
}
- (void) drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
{
if (layer == _hostLayer) {
CGSize size = layer.bounds.size;
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, 0, 0);
CGPathAddLineToPoint(path, NULL, size.width, size.height);
_hostLayer.path = path;
CGPathRelease(path);
}
}
- (IBAction)resizeWindow:(id)sender
{
[self.window setFrame:CGRectMake(100, 100, 1200, 800) display:YES animate:YES];
}
@end