vertically aligning text in NSTableView row
Asked Answered
U

5

16

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!

Can anyone suggest me any way to do it ??

Thanks,

Miraaj

Unearth answered 20/1, 2010 at 16:42 Comment(0)
P
21

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.

Pollie answered 20/1, 2010 at 16:46 Comment(1)
size assumes infinite width—it does not account for line wrapping. I suggest boundingRectForSize:options:, with the size from cellFrame, instead.Expunction
P
8

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:

enter image description here

and the height of the TableViewCell

enter image description here

enter image description here

Thanks Bryan for your help.

Pervasive answered 28/6, 2015 at 9:12 Comment(0)
R
3

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.

Rubberneck answered 26/12, 2018 at 21:25 Comment(1)
By far the simplest solution, thanks!Principium
L
0

@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)
    }
}
Lyon answered 13/2, 2018 at 1:34 Comment(0)
C
0

Just drawing the attributed string can yield strange results for some attributed strings (with superscript for example).

I’d suggest calling super in drawInterior…

  override func drawInterior(withFrame cellFrame: NSRect, in controlView: NSView) {
    super.drawInterior(withFrame: self.titleRect(forBounds: cellFrame), in: controlView)
}
Cano answered 11/8, 2021 at 16:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.