NSView添加到NSStatusItem按钮有一个不透明边框 [英] NSView added to NSStatusItem button has an opaque border

查看:412
本文介绍了NSView添加到NSStatusItem按钮有一个不透明边框的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在一个NSStatusItem用户代理,添加一个NSView子类作为NSStatusItem.button的子视图提供动画图标。



当点击图标时,视图周围有一个明显的不透明边框。



视图子类init读取:

   - (instancetype)initWithFrame:(NSRect)rect 
{
self = [super initWithFrame:rect];
if(self){
self.wantsLayer = YES;
self.layer.opaque = NO;
[self.layer addSublayer:self.background];
[self.layer addSublayer:self.foreground];
[self.layer addSublayer:self.symbol];
}
return self;
}

视图StatusView通过控制器添加到NSStatusBarItem的按钮: / p>

  self.statusItem.highlightMode = YES; 
[self.statusItem.button addSubview:self.statusView];

下面是鼠标左键后的样子:



$

解决方案

我花了很多时间阅读文档试图找出如何摆脱那个边框。我检查了我的视图,图层和子图层的不透明度。我设置背景颜色清除。我搞砸了阿尔法。我重写了我的视图没有层。没有什么可以摆脱那个不透明的约束,我准备扔在毛巾和提供我的内容通过一个NSImage setTemplate:是的。



作为最后一个努力来了解发生了什么,我写了一个简短的方法来遍历视图的层次结构,寻找不透明的视图:

   - (void)displayViewInfo:(NSView *)view 
{
NSLog(@view%@ \tisOpaque%d ,viberncy%d super%@,
view,view.isOpaque,view.allowsVibrancy,view.superview);
for(NSView * v in view.subviews){
[self displayViewInfo:v];
}
}



我找到属性 opaqueAncestor



从NSView子类的drawLayer:inContext:方法调用

  [self displayViewInfo:self.opaqueAncestor]; 

输出(含时间戳信息trimmed)如下:

  view< NSNextStepFrame:0x610000181380> isOpaque 1,vibrancy 0 super(null)
view< NSVisualEffectView:0x1006023e0> isOpaque 0,viberncy 1 super< NSNextStepFrame:0x610000181380>
view< NSStatusBarButton:0x600000161bc0> isOpaque 0,viberncy 1 super< NSVisualEffectView:0x1006023e0>
view< StatusView:0x6000001a02a0> isOpaque 0,viberncy 0 super< NSStatusBarButton:0x600000161bc0>

StatusView的opaqueAncestor原来是层次结构的根视图,不透明。我添加了allowVibrancy检查后的几个突变的方法。我发现有趣的是,StatusView的superviews允许活力,我的观点不是。属性文档 allowVibrancy 是含糊的,所以我添加到我的观点:

  (BOOL)allowVibrancy {return YES; } 

结果本身就是:





希望这个悲伤和救赎的故事会节省一些人的时间;它确实让我困惑。


I have been working on a NSStatusItem user agent that adds a NSView subclass as a subview of NSStatusItem.button to provide animated icons.

When left clicking on the icon, there is a noticeable opaque border around the view.

The view subclass's init reads:

- (instancetype)initWithFrame:(NSRect )rect
{
    self = [super initWithFrame:rect];
    if ( self ) {
        self.wantsLayer = YES;
        self.layer.opaque = NO;
        [self.layer addSublayer:self.background];
        [self.layer addSublayer:self.foreground];
        [self.layer addSublayer:self.symbol];
    }
    return self;
}

The view, StatusView, is added by a controller to the NSStatusBarItem's button:

    self.statusItem.highlightMode = YES;
    [self.statusItem.button addSubview:self.statusView];

Here is what it looked like after a left mouse down:

Not really the polished look I was hoping for.

解决方案

I spent a lot of time reading the documentation trying to figure out how get rid of that border. I checked for opacity in my view, layer and sublayers. I set background colors to clear. I messed with alpha. I re-wrote my view without layers. Nothing could get rid of that opaque bound and I was about ready to throw in the towel and provide my content via a NSImage with setTemplate:YES.

As a last ditch effort to understand what was happening, I wrote a short method to traverse the view's hierarchy looking for the view that was opaque:

- (void)displayViewInfo:(NSView *)view
{
    NSLog(@"view %@\tisOpaque %d, vibrancy %d super %@",
          view,view.isOpaque,view.allowsVibrancy, view.superview);
    for (NSView *v in view.subviews){
         [self displayViewInfo:v];
    }
}

I found the property opaqueAncestor while poring over the documentation for NSView and figured that might be a good place to start looking.

Called from my NSView subclass's drawLayer:inContext: method thusly.

[self displayViewInfo:self.opaqueAncestor];

The output (with timestamp info trimmed) looked like :

view <NSNextStepFrame: 0x610000181380>   isOpaque 1, vibrancy 0 super (null)
view <NSVisualEffectView: 0x1006023e0>   isOpaque 0, vibrancy 1 super <NSNextStepFrame: 0x610000181380>
view <NSStatusBarButton: 0x600000161bc0> isOpaque 0, vibrancy 1 super <NSVisualEffectView: 0x1006023e0>
view <StatusView: 0x6000001a02a0>        isOpaque 0, vibrancy 0 super <NSStatusBarButton: 0x600000161bc0>

The opaqueAncestor of StatusView turned out to be the root view for the hierarchy and all the subviews were reporting not opaque. I added the allowVibrancy check after a few mutations of the method. I found it interesting that the superviews of StatusView were allowing vibrancy and my view was not. The documentation on the property allowVibrancy was vaguely promising, so I added this to my view:

- (BOOL)allowVibrancy { return YES; }

The result speaks for itself:

Hopefully this tale of woe and redemption will save somebody some time; it sure had me baffled.

这篇关于NSView添加到NSStatusItem按钮有一个不透明边框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆