I have a small problem with NSTableView. When I am increasing height of a row in table, the text in it is aligned at top of row but I want to align it vertically centered!
Even if this is a very old question with an accepted answer, here's an alternate solution:
Go into the IB, select your NSTextField sitting in a NSTableCellView and add a new "Center Vertically in Container" constraint. You should also add horizontal constraints (which should probably be leading/trailing space set to 0 or whatever suits your needs).
Used this in an NSOutlineView and worked like a charm. Performance wasn't an issue in my case, as I didn't have many cells, but I would expect it's not worse than manually calculating sizes.
Here is the Swift version of the code building on the answer above:
import Foundation
import Cocoa
class VerticallyCenteredTextField : NSTextFieldCell
{
override func titleRectForBounds(theRect: NSRect) -> NSRect
{
var titleFrame = super.titleRectForBounds(theRect)
var titleSize = self.attributedStringValue.size
titleFrame.origin.y = theRect.origin.y - 1.0 + (theRect.size.height - titleSize.height) / 2.0
return titleFrame
}
override func drawInteriorWithFrame(cellFrame: NSRect, inView controlView: NSView)
{
var titleRect = self.titleRectForBounds(cellFrame)
self.attributedStringValue.drawInRect(titleRect)
}
}
Then I set the height of the tableView heightOfRow in the NSTableView:
func tableView(tableView: NSTableView, heightOfRow row: Int) -> CGFloat
{
return 30
}
Set the class of the NSTextFieldCell to be VerticallyCenteredTextField:
and the height of the TableViewCell
Thanks Bryan for your help.
This is a simple code solution that shows a subclass you can use to middle align a TextFieldCell.
the header
#import <Cocoa/Cocoa.h>
@interface MiddleAlignedTextFieldCell : NSTextFieldCell {
}
@end
the code
@implementation MiddleAlignedTextFieldCell
- (NSRect)titleRectForBounds:(NSRect)theRect {
NSRect titleFrame = [super titleRectForBounds:theRect];
NSSize titleSize = [[self attributedStringValue] size];
titleFrame.origin.y = theRect.origin.y - .5 + (theRect.size.height - titleSize.height) / 2.0;
return titleFrame;
}
- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView {
NSRect titleRect = [self titleRectForBounds:cellFrame];
[[self attributedStringValue] drawInRect:titleRect];
}
@end
This blog entry shows an alternative solution that also works well.
@iphaaw's answer updated for Swift 4 (note I also added "Cell" on the end of the class name for clarity, which also needs to match the class name in Interface Builder):
import Foundation
import Cocoa
class VerticallyCenteredTextFieldCell : NSTextFieldCell {
override func titleRect(forBounds theRect: NSRect) -> NSRect {
var titleFrame = super.titleRect(forBounds: theRect)
let titleSize = self.attributedStringValue.size
titleFrame.origin.y = theRect.origin.y - 1.0 + (theRect.size.height - titleSize().height) / 2.0
return titleFrame
}
override func drawInterior(withFrame cellFrame: NSRect, in controlView: NSView) {
let titleRect = self.titleRect(forBounds: cellFrame)
self.attributedStringValue.draw(in: titleRect)
}
}