NSView CALayer 不透明度疯狂

发布于 2024-11-26 03:27:07 字数 1563 浏览 0 评论 0原文

似乎我的 NSView 的图层属性有时不可编辑/错误。在下面的代码中,动画效果完美,一切看起来都很正常。 NSlogs 的输出始终是:

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

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

我在图层中使用 setneedsdisplay 并在 nsview 中使用 setneedsdisplay: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);
    }

It seems as though the layer's properties of my NSView are sometimes not editable/wrong. In the code below, the animation works perfectly, and all appears normal. The output from the NSlogs are always :

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

The first two logs look right, so even at animation did stop, the layer seems to operate normally. However, some time later, when I check the opacity it magically turned to 0. Further wrong, when I set the layer's opacity to 1, and check it immediately after, it still is 0. How is that possible?

I goofed around with setneedsdisplay in the layer and setneedsdisplay:YES in nsview and that
didn't help. Any suggestions are greatly appreciated.

- (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);
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梅倚清风 2024-12-03 03:27:07

通过创建图层支持的视图,然后尝试直接操作图层,您违反了基本的 CALayer/NSView 规则。

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

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

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

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

-[NSView setWantsLayer:] 文档;我还发现了一个 旧的 cocoa-dev 线程这很好地解释了这一点。

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

You're breaking a fundamental CALayer/NSView rule by creating a layer-backed view and then trying to manipulate the layer directly.

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

When you tell the view to use a layer before calling setLayer:, the view becomes "layer-backed" -- it is simply using the layer as a buffer and all drawing that you want to do should be done through the usual drawRect: and related methods. You are not allowed to touch the layer directly. If you change the order of those calls:

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

You now have a "layer-hosting" view, which means that the view just provides a space on the screen for the layer to be drawn into. In this case, you do your drawing directly into the layer. Since the contents of the layer become the contents of the view, you cannot add subviews or use the view's drawing mechanisms.

This is mentioned in the -[NSView setWantsLayer:] documentation; I also found an old cocoa-dev thread that explains it pretty well.

I'm not certain that this will fix your problem, but as far as I can see you're doing everything else correctly, such as setting the fill mode and updating the value after the animation finishes.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文