具有图层背景颜色的 OSX NSTextField 不起作用 [英] OSX NSTextField with layer background color not working

查看:21
本文介绍了具有图层背景颜色的 OSX NSTextField 不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下 NSTextField 的子类(与 NSTextFieldCell 的相应子类用于间距 [方法找到

I have the following subclass of NSTextField (with corresponding subclass of NSTextFieldCell for spacing [approach found here]). I'm trying to change the border color and background color on "focus", but it isn't working.

class TGTextField: NSTextField {
    override func viewWillDraw() {
        self.layer?.borderWidth = 1
        self.layer?.cornerRadius = 2
        self.textColor = NSColor(calibratedRed: 55/255, green: 54/255, blue: 54/255, alpha: 1)
        self.focusRingType = .None
        self.font = NSFont(name: "ProximaNova-Medium", size: 16)!

        setBlurredStyles()
    }

    private func setFocusedStyles() {
        self.layer?.borderColor = NSColor(calibratedRed: 92/255, green: 188/255, blue: 214/255, alpha: 1).CGColor
        self.layer?.backgroundColor = NSColor(calibratedRed: 247/255, green: 252/255, blue: 252/255, alpha: 1).CGColor
    }

    private func setBlurredStyles() {
        self.layer?.borderColor = NSColor(calibratedRed: 221/255, green: 221/255, blue: 221/255, alpha: 1).CGColor
        self.layer?.backgroundColor = NSColor.whiteColor().CGColor
    }

    override func becomeFirstResponder() -> Bool {
        if super.becomeFirstResponder() {
            dispatch_async(dispatch_get_main_queue(), {
                self.setFocusedStyles()
            })
            return true
        } else {
            return false
        }
    }

    override func resignFirstResponder() -> Bool {
        if super.resignFirstResponder() {
            dispatch_async(dispatch_get_main_queue(), {
                self.setBlurredStyles()
            })
            return true
        } else {
            return false
        }
    }
}

class TGTextFieldCell: NSTextFieldCell {
    override init(imageCell image: NSImage?) {
        super.init(imageCell: image)
    }

    override init(textCell aString: String) {
        super.init(textCell: aString)
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override func drawingRectForBounds(theRect: NSRect) -> NSRect {
        let rectInset = NSMakeRect(theRect.origin.x + 7, theRect.origin.y + 7, theRect.size.width, theRect.size.height)
        return super.drawingRectForBounds(rectInset)
    }
}

In fact, it appears that trying to set self.layer?.backgroundColor to anything anywhere doesn't work. I can't just set backgroundColor on the textfield itself, because based on the cell, the background color is offset.

How can I set the backgroundColor on the layer of an NSTextField subclass?

解决方案

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:

这篇关于具有图层背景颜色的 OSX NSTextField 不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆