Cocoa 如何更改包括三角形部分的NSPopover背景色?
如何更改Cocoa 如何更改包括三角形部分的NSPopover背景色?,cocoa,Cocoa,如何更改nspoover背景色包括三角形部分 不幸的是,这实际上是不可能的。NSPopover不是为可定制而设计的。如果您想要一个完全定制的外观,最好的选择可能是使用第三方、开源的NSpover替代品,如。我也遇到了同样的问题,但我试图避免将第三方UI元素添加到我的项目中,所以我看得更远。如果您在popover的contentViewController视图中覆盖drawRect:,设置如下颜色: [[NSColor whiteColor] setFill]; NSRectFill([self
nspoover
背景色包括三角形部分
不幸的是,这实际上是不可能的。NSPopover不是为可定制而设计的。如果您想要一个完全定制的外观,最好的选择可能是使用第三方、开源的NSpover替代品,如。我也遇到了同样的问题,但我试图避免将第三方UI元素添加到我的项目中,所以我看得更远。如果您在popover的
contentViewController
视图中覆盖drawRect:
,设置如下颜色:
[[NSColor whiteColor] setFill];
NSRectFill([self bounds]);
然后你会得到一个白色背景的popover,除了三角形/箭头连接到它相对的矩形。要解决此问题,您必须访问popover的边框视图,该视图恰好包含箭头:
NSView* borderView = [self.view.window valueForKeyPath:@"_borderView"];
我知道,这是一个私人API,但如果你的目标不包括将你的应用提交到应用商店,这是最简单的方法。现在,您也可以覆盖此视图的drawRect:
。为了避免像使用SDK更新重命名私有的\u borderView
属性这样的问题,我建议在引用它之前断言borderView是否存在
NSAssert(borderView, @"_borderView does not exist");
它实际上简单得多,并且不需要私有API 使视图控制器的根视图成为自定义类
@implementation MyPopoverRootView
-(void)viewDidMoveToWindow
{
NSView * aFrameView = [[self.window contentView] superview];
MyPopoverBackgroundView * aBGView =[[MyPopoverBackgroundView alloc] initWithFrame:aFrameView.bounds];
aBGView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
[aFrameView addSubview:aBGView positioned:NSWindowBelow relativeTo:aFrameView];
[super viewDidMoveToWindow];
}
@end
背景视图只是在其边界中绘制所需的颜色
@implementation MyPopoverBackgroundView
-(void)drawRect:(NSRect)dirtyRect
{
[[NSColor whiteColor] set];
NSRectFill(self.bounds);
}
@end
多亏了Stefanf,我才得以工作。下面是查看代码的Swift版本。如前所述,这应该是作为NSPover contentView设置的视图的类
class PopoverContentView:NSView {
var backgroundView:PopoverBackgroundView?
override func viewDidMoveToWindow() {
super.viewDidMoveToWindow()
if let frameView = self.window?.contentView?.superview {
if backgroundView == nil {
backgroundView = PopoverBackgroundView(frame: frameView.bounds)
backgroundView!.autoresizingMask = NSAutoresizingMaskOptions([.ViewWidthSizable, .ViewHeightSizable]);
frameView.addSubview(backgroundView!, positioned: NSWindowOrderingMode.Below, relativeTo: frameView)
}
}
}
}
class PopoverBackgroundView:NSView {
override func drawRect(dirtyRect: NSRect) {
NSColor.redColor().set()
NSRectFill(self.bounds)
}
}
Swift 3
override func viewDidMoveToWindow() {
guard let frameView = window?.contentView?.superview else {
return
}
let backgroundView = NSView(frame: frameView.bounds)
backgroundView.wantsLayer = true
backgroundView.layer?.backgroundColor = .white // colour of your choice
backgroundView.autoresizingMask = [.viewWidthSizable, .viewHeightSizable]
frameView.addSubview(backgroundView, positioned: .below, relativeTo: frameView)
}
如果您只想更改popover的背景颜色(包括三角形/箭头),我想您不需要创建NSView的子类。有背景色的图层视图就足够了
另外,您不需要调用super.viewdimovetowindow(),因为它的默认实现不起任何作用。这是我找到的解决这个问题的最简单方法。无需子类NSView或添加任何子视图
NSView *popoverView = [[[[self popover] contentViewController] view] superview];
[popoverView setWantsLayer:YES];
[[popoverView layer] setBackgroundColor:[[NSColor colorWithWhite:0.8 alpha:1] CGColor]];
获取popover根视图的superview,设置其图层的背景色。Mike Bedar的解决方案正在发挥作用,但只添加了一件事(为了使三角形填充背景色),即覆盖PopoOverContentView中的draw功能:
Stefanf&Mike Bedar针对Swift 4的解决方案:
您的府绸及其三角形现在将为绿色。很高兴我能帮忙!如果我的答案解决了你的问题,你应该点击左边的复选标记接受它:)可能的重复你可能想接受Stefanf的答案,因为他找到了一个解决方案。这是一个很棒的解决方案!我肯定认为这应该是选择的答案。但是如何更改三角形部分的颜色?MyPopoverRootView是扩展了NSPopover,还是您正在使用它作为PopOver的contentViewController?@MikeBedar这只是一个视图类。没有延伸这不会改变三角形的颜色。这里提到了设置frame属性来解决这个问题,但我不知道需要设置哪个帧以及设置什么。这改变了我的三角形颜色(10.15.5上的测试)现在我如何将我自己的视图分层到这个上面?在
NSView
子类中设置这个对我来说很有用。它的代码比公认的答案要少一点(这总是很好的)。谢谢view.wantsLayer=true'是键。谢谢这个代码到哪里去了?在用于nspover
的视图控制器内,这对我在macOS Mojave停止工作。它对你仍然有效吗?
override func draw(_ dirtyRect: NSRect) {
backColor.set() // backColor is NSColor
NSRectFill(self.bounds)
}
import Cocoa
class PopoverContentView:NSView {
var backgroundView:PopoverBackgroundView?
override func viewDidMoveToWindow() {
super.viewDidMoveToWindow()
if let frameView = self.window?.contentView?.superview {
if backgroundView == nil {
backgroundView = PopoverBackgroundView(frame: frameView.bounds)
backgroundView!.autoresizingMask = NSView.AutoresizingMask([.width, .height]);
frameView.addSubview(backgroundView!, positioned: NSWindow.OrderingMode.below, relativeTo: frameView)
}
}
}
}
class PopoverBackgroundView:NSView {
override func draw(_ dirtyRect: NSRect) {
NSColor.green.set()
self.bounds.fill()
}
}