NSView添加到NSStatusItem按钮有一个不透明边框 [英] NSView added to NSStatusItem button has an opaque border
问题描述
我一直在一个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屋!