OSX NSTextField with layer background color not working

前端 未结 2 852
无人及你
无人及你 2021-01-21 19:30

I have the following subclass of NSTextField (with corresponding subclass of NSTextFieldCell for spacing [approach found here]). I\'m trying to change

2条回答
  •  野趣味
    野趣味 (楼主)
    2021-01-21 19:52

    Looks like a simple problem... but requires a lot of hacky code. I have some working snippet for you.

    Make sure your text fields are layer backed!

    Get rid of all that custom stuff in the cell. Apple want to retire them soon... Not even sure any valid cases operate with cells:

    class TGTextFieldCell: NSTextFieldCell {
    
    }
    

    Next we get to the actual:

    class TGTextField: NSTextField
    

    Define a property holding focused state:

    private var isFocused = false
    

    Override becoming first responder as you did originally:

    override func becomeFirstResponder() -> Bool {
        if super.becomeFirstResponder() {
            isFocused = true
            return true
        } else {
            return false
        }
    }
    

    Unfortunately, we cannot capture the moment of blur easily. There are some long explanations for that in internet... but we will capture blur in a the event subscription:

        func subscribeForEndEdit(){
        self.drawsBackground = false
        NSNotificationCenter.defaultCenter().addObserver(self, selector:"didEndEdit:", name: NSControlTextDidEndEditingNotification, object: nil)
    }
    
    func didEndEdit(notification: NSNotification){
        isFocused = false
    }
    

    Now call that subscription in the constructors overrides:

    override init(frame frameRect: NSRect) {
        super.init(frame: frameRect)
    
        subscribeForEndEdit()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
    
        subscribeForEndEdit()
    }
    

    Now prevent background drawing:

        self.drawsBackground = false
    

    The final piece is changing background on drawing:

    override func drawRect(dirtyRect: NSRect) {
        //Draw cell content here
        super.cell?.drawInteriorWithFrame(dirtyRect, inView: self)
    
        if isFocused {
    
            self.layer?.backgroundColor = NSColor.redColor().CGColor
        } else {
    
            self.layer?.backgroundColor = NSColor.whiteColor().CGColor
        }
    
    
    }
    

    The entire file is:

    import Cocoa
    
    class TGTextField: NSTextField {
    
    private var isFocused = false
    
    override init(frame frameRect: NSRect) {
        super.init(frame: frameRect)
    
        subscribeForEndEdit()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
    
        subscribeForEndEdit()
    }
    
      func subscribeForEndEdit(){
        self.drawsBackground = false
        NSNotificationCenter.defaultCenter().addObserver(self, selector:"didEndEdit:", name: NSControlTextDidEndEditingNotification, object: nil)
    }
    
    func didEndEdit(notification: NSNotification){
        isFocused = false
    }
    
    
    override func drawRect(dirtyRect: NSRect) {
        //Draw cell content here
        super.cell?.drawInteriorWithFrame(dirtyRect, inView: self)
    
        if isFocused {
    
            self.layer?.backgroundColor = NSColor.redColor().CGColor
        } else {
    
            self.layer?.backgroundColor = NSColor.whiteColor().CGColor
        }
    
    
    }
    
    override func becomeFirstResponder() -> Bool {
        if super.becomeFirstResponder() {
            isFocused = true
            return true
        } else {
            return false
        }
    }
    
    deinit {
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }
    
    }
    
    class TGTextFieldCell: NSTextFieldCell {
    
    }
    

    Here is the picture of what I get:

提交回复
热议问题