web-dev-qa-db-ja.com

自動レイアウトのテキストでNSTextFieldを成長させる方法は?

Lionの自動レイアウトでは、テキストフィールド(およびラベル)が保持するテキストに合わせて簡単に拡大できるはずです。

テキストフィールドはInterface Builderで折り返すように設定されています。

これを行う簡単で信頼できる方法は何ですか?

38
Monolo

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];
}
48
Monolo

スウィフト4

編集可能な自動サイズ変更NSTextField

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_MAXCGFloat.greatestFiniteMagnitudeまたは大きな数を使用する場合のいくつかのバグ。バグは操作中に発生し、ユーザーがフィールド内のテキストを選択すると、スクロールして上下にスクロールして無限大にできます。さらに、ユーザーがテキストを入力すると、ユーザーが編集を終了するまでNSTextFieldは空白になります。最後に、ユーザーがNSTextFieldを選択してウィンドウのサイズを変更しようとした場合、self.frame.size.heightの値が大きすぎるとウィンドウがハングします。

7
Lore

受け入れられた答えはintrinsicContentSizeの操作に基づいていますが、すべての場合に必要なわけではありません。 Autolayoutは、(a)テキストフィールドにpreferredMaxLayoutWidthを指定し、(b)フィールドをeditableにしない場合、テキストフィールドの高さを拡大および縮小します。これらの手順により、テキストフィールドは固有の幅を決定し、自動レイアウトに必要な高さを計算できます。詳細は this answer および this answer を参照してください。

さらにあいまいなことに、テキストフィールドのeditable属性への依存関係から、フィールドでバインディングを使用していてConditionally Sets Editableオプションのクリアに失敗した場合、自動レイアウトは機能しなくなります。

4
spinacher