设置 NSTextField 垂直居中

Mac 开发中,设置一个 Label 是很常见的事情,但 Mac 中没有直接提供类似 iOS 中的 UILabel 类,只能使用 NSTextField 类;但在使用过程中发现,其中的字无法垂直居中,很是难看。网络上搜了一遍,有用的信息支离破碎,同时几年前的类方法已经被废弃了。

综合一下,参考苹果官方文档,NSTextField 内部有个 cell 对象,默认是 NSTextFieldCell,它负责绘制工作。因此自定义一个 RSVerticallyCenteredTextFieldCell 类继承自 NSTextFieldCell,绘制时设置垂直居中;再自定义一个 RSVerticallyCenteredTextField 类继承自 NSTextField,初始化时设置 cell 为自定义的 Cell 类;最后使用该自定义的 RSVerticallyCenteredTextField 类即可。

RSVerticallyCenteredTextFieldCell.swift

class RSVerticallyCenteredTextFieldCell: NSTextFieldCell {
var mIsEditingOrSelecting:Bool = false
override func drawingRect(forBounds theRect: NSRect) -> NSRect {
//Get the parent's idea of where we should draw
var newRect:NSRect = super.drawingRect(forBounds: theRect)
// When the text field is being edited or selected, we have to turn off the magic because it screws up
// the configuration of the field editor. We sneak around this by intercepting selectWithFrame and editWithFrame and sneaking a
// reduced, centered rect in at the last minute.
if !mIsEditingOrSelecting {
// Get our ideal size for current text
let textSize:NSSize = self.cellSize(forBounds: theRect)
//Center in the proposed rect
let heightDelta:CGFloat = newRect.size.height textSize.height
if heightDelta > 0 {
newRect.size.height -= heightDelta
newRect.origin.y += heightDelta/2
}
}
return newRect
}
override func select(withFrame rect: NSRect,
in controlView: NSView,
editor textObj: NSText,
delegate: Any?,
start selStart: Int,
length selLength: Int)//(var aRect: NSRect, inView controlView: NSView, editor textObj: NSText, delegate anObject: AnyObject?, start selStart: Int, length selLength: Int)
{
let arect = self.drawingRect(forBounds: rect)
mIsEditingOrSelecting = true;
super.select(withFrame: arect, in: controlView, editor: textObj, delegate: delegate, start: selStart, length: selLength)
mIsEditingOrSelecting = false;
}
override func edit(withFrame rect: NSRect,
in controlView: NSView,
editor textObj: NSText,
delegate: Any?,
event: NSEvent?)
{
let aRect = self.drawingRect(forBounds: rect)
mIsEditingOrSelecting = true;
super.edit(withFrame: aRect, in: controlView, editor: textObj, delegate: delegate, event: event)
mIsEditingOrSelecting = false
}
}
RSVerticallyCenteredTextFieldCell.swift

RSVerticallyCenteredTextField.swift

import Cocoa

class RSVerticallyCenteredTextField: NSTextField {

    override func draw(_ dirtyRect: NSRect) {
        super.draw(dirtyRect)
    }
    
    override init(frame frameRect: NSRect) {
        super.init(frame: frameRect)
        
        let cell = RSVerticallyCenteredTextFieldCell(textCell: "")
        self.cell = cell
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

参考链接

https://stackoverflow.com/questions/18259899/setting-the-cell-on-nstextfield

分类:Mac

Tagged as: ,

5 replies

  1. let cell = RSVerticallyCenteredTextFieldCell(textCell: “”)
    这段代码貌似报错 请问这是swfit 还是 object-c的

  2. 老哥,我是用分类重写的select和edit方法,但是我发现edit方法没有被调用,select方法只在编辑时被调用,现在我的情况是,只有在编辑状态时可以垂直居中,退出编辑状态时会恢复垂直居上,我该怎么办

  3. 这段代码有缺陷,无法设置背景色,背景色被一个白色的覆盖,但是很诡异,找不到这个白色的是个什么东西 ,见鬼

发表评论

Fill in your details below or click an icon to log in:

WordPress.com 徽标

您正在使用您的 WordPress.com 账号评论。 登出 /  更改 )

Google photo

您正在使用您的 Google 账号评论。 登出 /  更改 )

Twitter picture

您正在使用您的 Twitter 账号评论。 登出 /  更改 )

Facebook photo

您正在使用您的 Facebook 账号评论。 登出 /  更改 )

Connecting to %s

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理