如何更改NSPopover
背景颜色包括三角形部分?
答案 0 :(得分:51)
实际上它更简单,您不需要私有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
答案 1 :(得分:14)
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)
}
如果您只想更改弹出框的背景颜色(包括三角形/箭头),我认为您不需要创建NSView的子类。具有背景颜色的图层支持的NSView应该足够了。
此外,您不需要致电super.viewDidMoveToWindow()
,因为其默认实施不执行任何操作。
答案 2 :(得分:8)
感谢Stefanf,我得到了这个工作。这是View代码的Swift版本。如上所述,这应该是View设置为NSPopOver 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)
}
}
答案 3 :(得分:7)
我遇到了同样的问题,但我试图避免在项目中添加第三方UI元素,所以我进一步观察。您似乎在设置了以下颜色的情况下覆盖了弹出窗口drawRect:
视图中的contentViewController
:
[[NSColor whiteColor] setFill];
NSRectFill([self bounds]);
然后你最终会得到一个白色背景的弹出窗口,除了将它连接到相对于它的矩形的三角形/箭头。要解决这个问题,您必须访问碰巧包含箭头的popover的边框视图:
NSView* borderView = [self.view.window valueForKeyPath:@"_borderView"];
我知道,这是一个私有API,但如果您的目标不包括将您的应用提交到App Store,这是最简单的方法。现在,您也可以覆盖此视图的drawRect:
。为了避免像使用SDK更新重命名私有_borderView
属性这样的问题,我建议在引用之前断言borderView的存在。
NSAssert(borderView, @"_borderView does not exist");
答案 4 :(得分:5)
这是我发现的最简单的解决方案。无需子类化NSView或添加任何子视图。
NSView *popoverView = [[[[self popover] contentViewController] view] superview];
[popoverView setWantsLayer:YES];
[[popoverView layer] setBackgroundColor:[[NSColor colorWithWhite:0.8 alpha:1] CGColor]];
获取弹出窗口根视图的超级视图,设置其图层的背景颜色。
答案 5 :(得分:1)
不幸的是,这实际上是不可能的。 NSPopover不是为了定制而设计的。如果您想要完全自定义的外观,最好的选择可能是使用像INPopoverController这样的第三方开源NSPopover替换。
答案 6 :(得分:1)
Stefanf和Mike Bedar的Swift 4解决方案:
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()
}
}
在情节提要中,选择具有弹出窗口内容的视图,然后转到Identity Inspector
将类设置为PopoverContentView
您的弹出框及其三角形现在将变为绿色。
答案 7 :(得分:0)
Mike Bedar的解决方案正在发挥作用,但只增加了一件事(为了让三角形填充背景色),那就是覆盖中的 draw 函数> PopoverContentView :
override func draw(_ dirtyRect: NSRect) {
backColor.set() // backColor is NSColor
NSRectFill(self.bounds)
}