是否有一个“正确”的方式让NSTextFieldCell绘制垂直居中文本?

我有一个NSTableView与几个文本列。 默认情况下,这些列的dataCell是Apple的NSTextFieldCell类的一个实例,它完成各种奇妙的事情,但它绘制与单元格顶部alignment的文本,我希望文本在单元格中垂直居中。

NSTextFieldCell中有一个内部标志,可以用来垂直居中文本,而且工作起来非常漂亮。 然而,由于它是一个内部的标志,它的使用不受苹果的批准,它可能会在未来的版本中没有任何警告地消失。 我目前正在使用这个内部标志,因为它简单而有效。 苹果显然花了一些时间来实现这个function,所以我不喜欢重新实现它的想法。

所以; 我的问题是这样的: 什么是正确的方式来实现一些行为完全像苹果的NStextFieldCell,但绘制垂直居中文本,而不是顶端alignment?

为了logging,这里是我目前的“解决scheme”:

 @interface NSTextFieldCell (MyCategories) - (void)setVerticalCentering:(BOOL)centerVertical; @end @implementation NSTextFieldCell (MyCategories) - (void)setVerticalCentering:(BOOL)centerVertical { @try { _cFlags.vCentered = centerVertical ? 1 : 0; } @catch(...) { NSLog(@"*** unable to set vertical centering"); } } @end 

用法如下:

 [[myTableColumn dataCell] setVerticalCentering:YES]; 

其他答案不适用于多行。 因此,我最初继续使用未logging的cFlags.vCentered属性,但这导致我的应用程序被拒绝从应用程序商店。 我最终使用了Matt Bell解决scheme的修改版本,该解决scheme适用于多行,单词换行和截断的最后一行:

 -(void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView { NSAttributedString *attrString = self.attributedStringValue; /* if your values can be attributed strings, make them white when selected */ if (self.isHighlighted && self.backgroundStyle==NSBackgroundStyleDark) { NSMutableAttributedString *whiteString = attrString.mutableCopy; [whiteString addAttribute: NSForegroundColorAttributeName value: [NSColor whiteColor] range: NSMakeRange(0, whiteString.length) ]; attrString = whiteString; } [attrString drawWithRect: [self titleRectForBounds:cellFrame] options: NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesLineFragmentOrigin]; } - (NSRect)titleRectForBounds:(NSRect)theRect { /* get the standard text content rectangle */ NSRect titleFrame = [super titleRectForBounds:theRect]; /* find out how big the rendered text will be */ NSAttributedString *attrString = self.attributedStringValue; NSRect textRect = [attrString boundingRectWithSize: titleFrame.size options: NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesLineFragmentOrigin ]; /* If the height of the rendered text is less then the available height, * we modify the titleRect to center the text vertically */ if (textRect.size.height < titleFrame.size.height) { titleFrame.origin.y = theRect.origin.y + (theRect.size.height - textRect.size.height) / 2.0; titleFrame.size.height = textRect.size.height; } return titleFrame; } 

(这段代码假定为ARC;如果使用手动内存pipe理,则在attrString.mutableCopy之后添加一个autorelease)

重写NSCell的-titleRectForBounds:应该这样做 – 这是负责告诉单元格在哪里绘制文本的方法:

 - (NSRect)titleRectForBounds:(NSRect)theRect { NSRect titleFrame = [super titleRectForBounds:theRect]; NSSize titleSize = [[self attributedStringValue] size]; titleFrame.origin.y = theRect.origin.y + (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]; } 

仅供参考,这工作得很好,虽然我还没有设法让它保持中心,当你编辑单元格…我有时有大量的文本单元格,这个代码可能会导致它们错位,如果文字高度更大然后它试图垂直居中它的单元格。这是我修改的方法:

 - (NSRect)titleRectForBounds:(NSRect)theRect { NSRect titleFrame = [super titleRectForBounds:theRect]; NSSize titleSize = [[self attributedStringValue] size]; // test to see if the text height is bigger then the cell, if it is, // don't try to center it or it will be pushed up out of the cell! if ( titleSize.height < theRect.size.height ) { titleFrame.origin.y = theRect.origin.y + (theRect.size.height - titleSize.height) / 2.0; } return titleFrame; } 

对于任何尝试使用Matt Ball的drawInteriorWithFrame:inView:方法的人来说,如果将单元格设置为绘制背景,则不会再绘制背景。 为了解决这个问题,添加一些东西

 [[NSColor lightGrayColor] set]; NSRectFill(cellFrame); 

drawInteriorWithFrame:inView:方法的开始。

虽然这是一个很老的问题

我相信NSTableView实现的默认样式是严格意图用于所有相同大小和字体的单行文本显示。

在这种情况下,我build议,

  1. 设置字体。
  2. 调整rowHeight

也许你会得到安静密集的行。 然后,通过设置intercellSpacing给他们填充。

例如,

  core_table_view.rowHeight = [NSFont systemFontSizeForControlSize:(NSSmallControlSize)] + 4; core_table_view.intercellSpacing = CGSizeMake(10, 80); 

在这里你将得到两个财产调整。

在这里输入图像说明

这对于多行文本不起作用,但是如果不需要多行支持,则对于快速垂直中心来说足够好。

我有同样的问题,这是我做的解决scheme:

1)在Interface Builder中,select您的NSTableCellView。 确保它与Size Inspector中的行高一样大。 例如,如果你的行高是32,那么你的单元格高度是32

2)确保你的细胞放置在你的排(我的意思是可见的)

3)在您的单元格内select您的TextField并转到您的尺寸检查器

4)您应该看到“排列”项目并select“在容器中垂直居中”

– > TextField将自己居中在单元格中

不行。正确的方法是将字段放在另一个视图中,并使用自动布局或父视图的布局来定位它。