NSTextField 子类化后淡出
Posted
技术标签:
【中文标题】NSTextField 子类化后淡出【英文标题】:NSTextField Fades Out After Subclassing 【发布时间】:2017-04-08 10:07:28 【问题描述】:我使用以下代码对 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 有关。
每当我从 textfield 上的 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
。
感谢您的建议!但这会导致占位符在第一次加载时倒置,并且淡入/淡出问题仍然存在。
【参考方案1】:
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
【讨论】:
我不确定你所说的 draw 方法是什么意思,应该只用于绘制视图。在绘制视图时,您还设置了正确的属性,还是我弄错了?你能更深入一点吗?此外,当您使用上面所说的子层时,仍然会绘制边框,并且没有在 NSTextField 上执行任何属性 您在 draw 方法中设置了许多文本字段的颜色属性,我认为这不是一个好地方。您可以在 viewDidLoad 中完成所有这些操作,例如只需一个参考或甚至使用 didSet。 Draw 方法用于创建无法使用自己的属性创建的自定义视图。我不确定我是否理解你关于属性的评论的最后一部分,你能给我举个例子吗? 嗯,但是一旦您在不同的 NSTextFields 中使用此文本字段样式,您是否不需要每次都在每个 viewDidLoad 中运行此代码?那个时候子类会更有用吗?所以这就是为什么我认为我可以在 draw 方法中设置颜色属性。关于我之前评论的最后一部分,如果我使用上面的代码,我的 NSTextField 仍然会画一个边框,尽管上面的代码不应该这样做。 ok ,在这种情况下,子类化您的NSTextField
并覆盖 init
方法并在其中设置颜色。当您在 draw 中设置它时,每次视图更改时都会调用 draw 方法,并且您会一遍又一遍地设置属性,但是如果您在初始化程序中设置它,则只设置一次。对于边框部分,我认为您正在寻找isBordered = false
我还通过 NSTextFieldCell 更改了文本字段的插图,所以如果我设置 isBordered = false
,就会中断。因此我使用borderWidth = 0。关于init 的覆盖的最后一个问题。 NSTextField 的覆盖需要一个框架(override init(frame frameRect: NSRect))
,我在哪里设置它以便我可以返回super.init()?
。抱歉,对 Xcode 中的所有内容都很陌生,仍在学习中!以上是关于NSTextField 子类化后淡出的主要内容,如果未能解决你的问题,请参考以下文章