我试图动画自定义UIView的边界,同时也保持其层的大小与其父视图相同。为了做到这一点,我试着让图层的边界在它的父视图旁边动起来。我需要图层调用drawLayer:withContext作为它的动画,所以我的自定义绘图将随着边界正确地改变大小。
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];
为什么边界不报告一个变化作为它的动画(不只是最后一帧)?我做错了什么?
这可能有帮助,也可能没有帮助…
很多人都不知道Core Animation有一个非常酷的功能,允许你定义自己的图层属性,这样它们就可以被动画化。我使用的一个例子是给CALayer子类一个thickness
属性。当我用Core Animation制作动画时…
CABasicAnimation* ba = [CABasicAnimation animationWithKeyPath:@"thickness"];
ba.toValue = @10.0f;
ba.autoreverses = YES;
[lay addAnimation:ba forKey:nil];
…效果是在整个动画中反复调用drawInContext:
或drawLayer:...
,允许我在每个时刻根据其当前 thickness
属性值(动画过程中的中间值)反复更改图层的绘制方式。
在我看来,可能是你所追求的东西。如果是这样,您可以在这里找到一个可下载的示例:
https://github.com/mattneub/Programming-iOS-Book-Examples/tree/master/ch17p498customAnimatableProperty讨论(从我的书)在这里:
http://www.apeth.com/iOSBook/ch17.html _making_a_property_animatable
这是因为您要绘制的图层与屏幕上显示的图层不同。
当你动画一个图层属性时,它会立即被设置为模型层的最终值,(正如你已经注意到的),而实际的动画是在表示层完成的。
您可以访问表示层并查看动画属性的实际值:
CALayer *presentationLayer = (CALayer *)[self.bg.layer presentationLayer];
...
因为你没有提供你的drawLayer:withContext
方法,这是不清楚你想在动画期间画什么,但如果你想动画自定义属性,这里是一个很好的教程。
首先,图层支持(或托管)视图的图层总是调整大小以适应其父视图的边界。如果你将视图设置为图层委托,那么视图将在每一帧接收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