NSTextField子类化后会淡出

7
我已经使用以下代码对NSTextField进行了子类化:

我已经使用以下代码对NSTextField进行了子类化:

import Cocoa

class CustomSearchField: NSTextField {
    override func draw(_ dirtyRect: NSRect) {
        self.wantsLayer = true
        let textFieldLayer = CALayer()
        self.layer = textFieldLayer
        self.backgroundColor = NSColor.white
        self.layer?.backgroundColor = CGColor.white
        self.layer?.borderColor = CGColor.white
        self.layer?.borderWidth = 0
        super.cell?.draw(withFrame: dirtyRect, in: self)
    }
}

class CustomSearchFieldCell: NSTextFieldCell {
    override func drawingRect(forBounds rect: NSRect) -> NSRect {
        let minimumHeight = self.cellSize(forBounds: rect).height
        let newRect = NSRect(x: rect.origin.x + 25, y: (rect.origin.y + (rect.height - minimumHeight) / 2) - 4, width: rect.size.width - 50, height: minimumHeight)

        return super.drawingRect(forBounds: newRect)
    }
}

这一切都很好地运作了,它正如我所期望的绘制了我的NSTextField。唯一的问题是,一旦我将界面的其他部分设置为第一个响应者(单击NSTextField之外的区域),NSTextField内部的文本(占位符或填充文本)就会变淡。一旦我再次点击它,它就会恢复。我已经搜索了相当长时间了,但无法弄清楚这是为什么。我只希望文本始终可见,而不是闪烁不定。
这与我添加的CALayer样式有关。
每当我从viewDidLoad中运行相同的设置到文本框上时,它都能完美地工作。例如:
class ViewController: NSViewController {
    @IBOutlet weak var searchField: NSTextField!

    override func viewDidLoad() {
        initCustomSearchField()
    }

    private func initCustomSearchField() {
        searchField.wantsLayer = true
        let textFieldLayer = CALayer()
        searchField.layer = textFieldLayer
        searchField.backgroundColor = NSColor.white
        searchField.layer?.backgroundColor = CGColor.white
        searchField.layer?.borderColor = CGColor.white
        searchField.layer?.borderWidth = 0
        searchField.delegate = self
    }
}

不要在每次绘制时创建和设置属性,只需在一开始或更改时设置它们。不要调用 super.cell?.draw,而是调用 super.draw - Willeke
谢谢您的建议!但是这会导致第一次加载时占位符倒置,淡入/淡出问题仍然存在。 - user2023106
1个回答

4

draw 方法应该被用于绘制视图而不是设置属性。关于你的问题,不要直接设置 self.layer,而是使用 sublayer

我对你的代码的建议:

class CustomTextField :NSTextField {

    override init(frame frameRect: NSRect) {
        super.init(frame: frameRect)

        setupView()
    }

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

    func setupView(){
        textColor = .green
    }
}

class CustomTextFieldCell: NSTextFieldCell {

    override init(textCell string: String) {
        super.init(textCell: string)
        setupView()
    }

    required init(coder: NSCoder) {
        super.init(coder: coder)

        setupView()
    }

    func setupView(){
        backgroundColor = .red
    }


    override func drawingRect(forBounds rect: NSRect) -> NSRect {
        let newRect = NSRect(x: (rect.width - rect.width/2)/2, y: 0, width: rect.width/2, height: 20)
        return super.drawingRect(forBounds:newRect)
    }

    override func draw(withFrame cellFrame: NSRect, in controlView: NSView) {
        super.draw(withFrame: cellFrame, in: controlView)
        controlView.layer?.borderColor = NSColor.white.cgColor
        controlView.layer?.borderWidth = 2
    }

}

enter image description here


我不确定你所说的绘制方法只应用于视图的意思。在绘制视图时,您还设置属性,对吗?您能详细解释一下吗?另外,当使用上面提到的子层时,边框仍然会被绘制,并且NSTextField上的任何属性都不会被执行。 - user2023106
2
你在draw方法中设置了很多textfield的颜色属性,我认为这不是一个好的做法。你可以在viewDidLoad中使用引用或者使用didSet来完成所有这些操作。Draw方法用于创建无法使用其自身属性创建的自定义视图。我不确定我是否理解了你关于属性的最后一部分评论,你能给我举个例子吗? - user7649191
2
好的,那么请子类化您的 NSTextField 并重写 init 方法并在其中设置颜色。当您在 draw 中设置时,每次视图更改时都会调用 draw 方法并且您一遍又一遍地设置属性,但是如果您在初始化程序中设置它,则只设置一次。至于边框部分,我认为您正在寻找 isBordered = false - user7649191
我不太清楚边框为什么会表现出那种方式,但我能想到的唯一解决方法是使用相同颜色的边框。我已经更新了代码。希望有所帮助。 - user7649191
谢谢你的帮助,这解决了我的问题。我不确定为什么我在初始化时遇到了这么大的困难,因为这也是我想到的。也许我打错了一个字母导致了错误。无论如何,今天学到了很多。我稍微调整了一下,现在一切都正常运行。 - user2023106
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接