NSTextFieldCellに垂直方向に中央揃えのテキストを描画させる「正しい」方法はありますか?
-
22-07-2019 - |
質問
複数のテキスト列を持つ NSTableView
があります。デフォルトでは、これらの列の dataCell
はAppleの NSTextFieldCell
クラスのインスタンスであり、あらゆる種類の素晴らしいことを行いますが、セルの上部に揃えてテキストを描画します。そして、テキストをセルの垂直方向の中央に配置します。
NSTextFieldCell
には、テキストを垂直方向に中央揃えするために使用できる内部フラグがあり、美しく機能します。ただし、内部フラグであるため、その使用はAppleによって認可されておらず、将来のリリースで警告なしに単純に消滅する可能性があります。この内部フラグはシンプルで効果的であるため、現在使用しています。 Appleは明らかにこの機能の実装にしばらく時間を費やしてきたので、再実装するという考えは嫌いです。
そう;私の質問は次のとおりです。 AppleのNStextFieldCellとまったく同じように動作するが、上揃えではなく垂直中央揃えのテキストを描画するものを実装する正しい方法は何ですか?
記録については、現在の" solution"は次のとおりです。
@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];
解決
他の回答は、複数の行で機能しませんでした。そのため、最初はドキュメント化されていない cFlags.vCentered
プロパティを使用し続けましたが、そのためアプリがアプリストアから拒否されました。最終的に、複数行、ワードラップ、切り捨てられた最終行で機能するMatt Bellのソリューションの修正版を使用しました。
-(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を想定しています。手動メモリ管理を使用する場合、attrString.mutableCopyの後に自動リリースを追加します)
他のヒント
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];
}
FYI、これはうまく機能しますが、セルを編集するときに中央にとどまることができませんでした...大量のテキストを含むセルがあり、このコードはテキストが高さは、垂直方向の中央に配置しようとしているセルよりも大きくなります。変更した方法は次のとおりです。
- (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実装のデフォルトスタイルは、すべて同じサイズの1行のテキスト表示のみを対象としています&amp;フォント。
その場合、お勧めします
- フォントを設定します。
-
rowHeight
を調整します。
たぶん静かに密な行を取得するでしょう。次に、 intercellSpacing
を設定してパディングを行います。
たとえば、
core_table_view.rowHeight = [NSFont systemFontSizeForControlSize:(NSSmallControlSize)] + 4;
core_table_view.intercellSpacing = CGSizeMake(10, 80);
ここでは、2つのプロパティ調整で得られるものです。
これは複数行のテキストでは機能しませんが、複数行のサポートが必要ない場合は、垂直方向の中央にすばやく移動するには十分です。
私は同じ問題を抱えていましたが、ここに私がした解決策があります:
1)Interface Builderで、NSTableCellViewを選択します。サイズインスペクターの行の高さと同じ大きさであることを確認します。たとえば、行の高さが32の場合、セルの高さを32にします
2)セルが行内に適切に配置されていることを確認します(表示されていることを意味します)
3)セル内のTextFieldを選択し、サイズインスペクターに移動します
4)&quot; Arrange&quot;が表示されます。アイテムを選択し、「コンテナの垂直方向中央に配置」を選択します
-&gt; TextFieldはセルの中央に配置されます
いいえ。正しい方法は、フィールドを別のビューに配置し、自動レイアウトまたはその親ビューのレイアウトを使用して配置することです。