How to change NSPopover background color include triangle part?

后端 未结 8 544
无人及你
无人及你 2020-12-02 23:25

How can I change NSPopover background color include triangle part?

\"enter

相关标签:
8条回答
  • 2020-12-02 23:57

    It's actually much simpler and you won't need private API.

    Make the root view of your view controller a custom class

    @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
    

    Your background view just draws the desired color in its bounds.

    @implementation MyPopoverBackgroundView
    
    -(void)drawRect:(NSRect)dirtyRect
    {
        [[NSColor whiteColor] set];
        NSRectFill(self.bounds);
    }
    
    @end
    
    0 讨论(0)
  • 2020-12-03 00:03

    Here's the easiest solution to this issue that I've found. No need to subclass NSView or add any subviews.

    NSView *popoverView = [[[[self popover] contentViewController] view] superview];
    [popoverView setWantsLayer:YES];
    [[popoverView layer] setBackgroundColor:[[NSColor colorWithWhite:0.8 alpha:1] CGColor]];
    

    Get the superview of the root view of the popover, set its layer's background color.

    0 讨论(0)
  • 2020-12-03 00:04

    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)
    
    }
    

    If you want to change only the background colour of the popover (including the triangle/arrow), I figured that you don't need to create a subclass of NSView. A layer-backed NSView with a background colour should suffice.

    Also, you don't need to call super.viewDidMoveToWindow() because its default implementation does nothing.

    0 讨论(0)
  • 2020-12-03 00:07

    Unfortunately, this isn't really possible. NSPopover wasn't designed to be customizable. If you want a completely customized appearance, your best bet is probably to use a third-party, open-source NSPopover replacement like INPopoverController.

    0 讨论(0)
  • 2020-12-03 00:07

    The solution by Mike Bedar is working, but with adding just one more thing (in order to get the triangle filled with background color), and that is to override the draw function inside the PopoverContentView as well:

     override func draw(_ dirtyRect: NSRect) {
        backColor.set() // backColor is NSColor
        NSRectFill(self.bounds)
    }
    
    0 讨论(0)
  • 2020-12-03 00:11

    Thanks to Stefanf I got this working. Here is a Swift version of the View code. As noted, this should be the class for the View set as your 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)
        }
    }
    
    0 讨论(0)
提交回复
热议问题