NSTextField intrinsicContentSize始终返回{NSViewNoInstrinsicMetric,15},宽度不会调整

时间:2018-04-07 18:33:09

标签: cocoa autolayout nstextfield

我在视图中使用自动布局获得了一对可编辑的文本字段。 (为了完整起见,它们位于可编辑表格中的NSTableRowView内,但我认为这不重要。)

Editable text fields in a table row view

我希望字段根据内容调整宽度,特别是在编辑后。

但是,NSTextField不合作。每当编辑字段结束编辑时,我都会添加一些代码来记录intrinsicContentSize,并且值始终 { NSViewNoInstrinsicMetric, 15 },这意味着该字段没有固有的宽度。

我看过很多关于多行NSTextField和纵向(高度)调整大小,包装等的帖子,但我找不到任何适用于此处的问题或答案。这些字段都设置为“使用单行”,“剪辑”和“滚动”。

我已尝试发送字段updateConstraintsinvalidateIntrinsicContentSize消息,但它们似乎没有任何效果。

我知道我可以创建NSTextField的子类并破解它,但我不明白为什么这不起作用。或者NSTextField可能根本没有内在宽度,但我无法在任何地方找到记录。

注意:以前只设置field.editable = NO的答案不足;这些字段必须是可编辑的。

1 个答案:

答案 0 :(得分:0)

这是我的黑客:

//
// Create a special text field subclass that provides an intrinsic width for its content.
// Editable NSTextFields normally do not have an intrinsic width, because I guess that would just be too weird.
// This field returns an intrinsic width when not being edited, and the width of its superview when it is.
//

@interface ResizingPatternTextField : NSTextField
@end

@implementation ResizingPatternTextField

- (BOOL)becomeFirstResponder
{
    BOOL willEdit = [super becomeFirstResponder];
    if (willEdit)
        [self invalidateIntrinsicContentSize];
    return willEdit;
}

- (void)textDidEndEditing:(NSNotification*)notification
{
    [super textDidEndEditing:notification];
    [self invalidateIntrinsicContentSize];
}

- (NSSize)intrinsicContentSize
{
    NSSize intrinsiceSize = super.intrinsicContentSize;
    if (self.currentEditor!=nil)
        {
        // The field is currently being edited: return the width of the superview as the intrinsic width
        // This should cause the field to expand to it's maximum width, within the constraints of the layout
        intrinsiceSize.width = self.superview.bounds.size.width;
        }
    else
        {
        // If the field isn't being edited and it's editable: calculate the width of the field ourselves
        if (self.editable)
            {
            NSDictionary* textAttrs = @{ NSFontAttributeName: self.font };
            NSSize textSize = [self.stringValue sizeWithAttributes:textAttrs];
            // Return an intrinsic size with a little padding, rounded up to the nearest whole integer
            intrinsiceSize.width = CGCeiling(textSize.width+7.0);
            }
        }
    return intrinsiceSize;
}

注意:

  • 7.0分的填充值是固定的(对于"小"控件大小)并且不是一般解决方案
  • CGCeiling只是ceil()
  • 的一个宏
  • 当内在宽度非常宽时,您必须确保拥抱,抗压缩和其他布局约束呈现令人满意的布局。 (无论如何你应该这样做,但这里非常重要。)