如何更改NSPopover背景颜色包括三角形部分?

时间:2013-11-14 13:15:23

标签: cocoa

如何更改NSPopover背景颜色包括三角形部分?

enter image description here

8 个答案:

答案 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解决方案:

  1. 转到“文件”->“新文件”->“可可类”
  2. 为您的班级命名。例如。 PopoverContentView。确保它是NSView的子类
  3. 将文件内容设置为:
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()
    }
}
  1. 在情节提要中,选择具有弹出窗口内容的视图,然后转到Identity Inspector

  2. 将类设置为PopoverContentView

您的弹出框及其三角形现在将变为绿色。

答案 7 :(得分:0)

Mike Bedar的解决方案正在发挥作用,但只增加了一件事(为了让三角形填充背景色),那就是覆盖中的 draw 函数> PopoverContentView

 override func draw(_ dirtyRect: NSRect) {
    backColor.set() // backColor is NSColor
    NSRectFill(self.bounds)
}