NSView CALayer Opacity Madness

时间:2011-07-24 09:39:33

标签: objective-c cocoa calayer nsview opacity

好像我的NSView的图层属性有时不可编辑/错误。在下面的代码中,动画效果很好,一切都显得正常。 NSlog的输出始终为:

anim over opacity = 1.00000
first opacity = 0.50000
current opacity = 0.00000
updated opacity = 0.00000

前两个日志看起来正确,所以即使在动画停止时,该层似乎也能正常运行。然而,一段时间后,当我检查不透明度时,它神奇地转向0.更进一步的错误,当我将图层的不透明度设置为1,然后立即检查它,它仍然是0.这怎么可能?

我在图层中使用setneedsdisplay和setneedsdisplay进行了讨论:nsview中的YES和那个 没有帮助。非常感谢任何建议。

- (void) someSetupAnimationMethod {
        aLayer = [CALayer layer];
        [theView setWantsLayer:YES];
        [theView setLayer:aLayer];

        [aLayer setOpacity:0.0];
        CABasicAnimation *opacity = [CABasicAnimation animationWithKeyPath:@"opacity"];
        opacity.byValue = [NSNumber numberWithFloat:1.0];
        opacity.duration = 0.3;
        opacity.delegate = self;
        opacity.fillMode = kCAFillModeForwards;
        opacity.removedOnCompletion = NO;
        [opacity setValue:@"opacity done" forKey:@"animation"];
        [aLayer addAnimation:opacity forKey:nil];
    }

    - (void) animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
        if([[anim valueForKey:@"animation"] isEqualToString:@"opacity done"]) {
           NSLog(@"anim over opacity = %f", aLayer.opacity);
           aLayer.opacity = 0.5;
           [aLyaer removeAllAnimations];
           NSLog(@"first opacity = %f", aLayer.opacity);
        }
    }

    - (void) someLaterMethod {
        NSLog(@"current opacity = %f", aLayer.opacity);
        aLayer.opacity = 1.0;
        NSLog(@"updated opacity = %f", aLayer.opacity);
    }

1 个答案:

答案 0 :(得分:8)

您通过创建图层支持的视图然后尝试直接操作图层来破坏基本的CALayer / NSView规则。

aLayer = [CALayer layer];
[theView setWantsLayer:YES];
[theView setLayer:aLayer];

当您在调用setLayer:之前告诉视图使用图层时,视图变为“图层支持” - 它只是将图层用作缓冲区,并且您要执行的所有绘图都应该完成通过通常的drawRect:和相关方法。您不能直接触摸图层。如果您更改这些呼叫的顺序:

[theView setLayer:aLayer];
[theView setWantsLayer:YES];

您现在拥有“图层托管”视图,这意味着视图仅在屏幕上为要绘制的图层提供空间。在这种情况下,您可以直接在图层中绘制图形。由于图层的内容成为视图的内容,因此无法添加子视图或使用视图的绘图机制。

-[NSView setWantsLayer:]文档中提到了这一点;我还发现old cocoa-dev thread很好地解释了它。

我不确定这会解决您的问题,但据我所知,您正在正确地执行其他操作,例如设置填充模式并在动画完成后更新值。