Lionの自動レイアウトでは、テキストフィールド(およびラベル)が保持するテキストに合わせて簡単に拡大できるはずです。
テキストフィールドはInterface Builderで折り返すように設定されています。
これを行う簡単で信頼できる方法は何ですか?
intrinsicContentSize
のメソッドNSView
は、ビュー自体がその固有のコンテンツサイズと見なしているものを返します。
NSTextField
は、セルのwraps
プロパティを考慮せずにこれを計算するため、1行に配置されている場合、テキストの寸法を報告します。
したがって、NSTextField
のカスタムサブクラスは、このメソッドをオーバーライドして、セルのcellSizeForBounds:
メソッドによって提供されるような、より適切な値を返すことができます。
-(NSSize)intrinsicContentSize
{
if ( ![self.cell wraps] ) {
return [super intrinsicContentSize];
}
NSRect frame = [self frame];
CGFloat width = frame.size.width;
// Make the frame very high, while keeping the width
frame.size.height = CGFLOAT_MAX;
// Calculate new height within the frame
// with practically infinite height.
CGFloat height = [self.cell cellSizeForBounds: frame].height;
return NSMakeSize(width, height);
}
// you need to invalidate the layout on text change, else it wouldn't grow by changing the text
- (void)textDidChange:(NSNotification *)notification
{
[super textDidChange:notification];
[self invalidateIntrinsicContentSize];
}
Peter LapisuのObjective-Cの投稿に基づいています
サブクラスNSTextField
、以下のコードを追加します。
override var intrinsicContentSize: NSSize {
// Guard the cell exists and wraps
guard let cell = self.cell, cell.wraps else {return super.intrinsicContentSize}
// Use intrinsic width to jive with autolayout
let width = super.intrinsicContentSize.width
// Set the frame height to a reasonable number
self.frame.size.height = 750.0
// Calcuate height
let height = cell.cellSize(forBounds: self.frame).height
return NSMakeSize(width, height);
}
override func textDidChange(_ notification: Notification) {
super.textDidChange(notification)
super.invalidateIntrinsicContentSize()
}
self.frame.size.height
を「妥当な数」に設定avoidsFLT_MAX
、CGFloat.greatestFiniteMagnitude
または大きな数を使用する場合のいくつかのバグ。バグは操作中に発生し、ユーザーがフィールド内のテキストを選択すると、スクロールして上下にスクロールして無限大にできます。さらに、ユーザーがテキストを入力すると、ユーザーが編集を終了するまでNSTextField
は空白になります。最後に、ユーザーがNSTextField
を選択してウィンドウのサイズを変更しようとした場合、self.frame.size.height
の値が大きすぎるとウィンドウがハングします。
受け入れられた答えはintrinsicContentSize
の操作に基づいていますが、すべての場合に必要なわけではありません。 Autolayoutは、(a)テキストフィールドにpreferredMaxLayoutWidth
を指定し、(b)フィールドをeditable
にしない場合、テキストフィールドの高さを拡大および縮小します。これらの手順により、テキストフィールドは固有の幅を決定し、自動レイアウトに必要な高さを計算できます。詳細は this answer および this answer を参照してください。
さらにあいまいなことに、テキストフィールドのeditable
属性への依存関係から、フィールドでバインディングを使用していてConditionally Sets Editable
オプションのクリアに失敗した場合、自動レイアウトは機能しなくなります。