How to change NSPopover background color include triangle part?

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

How can I change NSPopover background color include triangle part?

\"enter

相关标签:
8条回答
  • 2020-12-03 00:14

    Stefanf & Mike Bedar's solution for Swift 4:

    1. Go to File->New File->Cocoa Class
    2. Name your class. eg. PopoverContentView. Make sure it is a subclass of NSView
    3. Set the contents of the file to:
    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. In your storyboard, select the view which has your popover content and go to the Identity Inspector

    2. Set the Class to PopoverContentView

    Your popover and its triangle will now be green.

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

    I faced the same problem, but I'm trying to avoid adding third party UI elements to my project, so I looked further. It seems if you override drawRect: in the view of your popover's contentViewController with setting a color like:

    [[NSColor whiteColor] setFill];
    NSRectFill([self bounds]);
    

    then you'll end up having a popover with white background, except the triangle/arrow that connects it to the rect it is relative to. For solving that, you have to access the popover's border view which happened to contain the arrow:

    NSView* borderView = [self.view.window valueForKeyPath:@"_borderView"];
    

    I know, it is a private API, but if your goals not include submitting your app to the App Store, this is the easiest way to go. Now you can override the drawRect: for this view as well. To avoid problems like having the private _borderView property renamed with an SDK update, I suggest to assert for the borderView's existence before referencing it.

    NSAssert(borderView, @"_borderView does not exist");
    
    0 讨论(0)
提交回复
热议问题