NSTextField宽度和自动布局

时间:2013-02-01 09:28:07

标签: cocoa nstextfield nstextview autolayout

我正在尝试以编程方式创建NSTextField

我想将此NSTextField用于自动布局,因此其宽度将自动定义以显示整行(只有一行文字)。

问题是textField.intrinsicContentSizetextField.fittingSize都有水平坐标的-1和0值,因为下面代码的输出是: textField.intrinsicContentSize={-1, 21} textField.fittingSize={0, 21}

代码:

NSTextField* textField = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 10, 24)];    
NSString* str = @"One line of text here.";
[textField setStringValue: str];
[textField setTranslatesAutoresizingMaskIntoConstraints:NO];
[textField invalidateIntrinsicContentSize];

NSLog(@"textField.intrinsicContentSize=%@", NSStringFromSize(textField.intrinsicContentSize));
NSLog(@"textField.fittingSize=%@", NSStringFromSize(textField.fittingSize));

这使得文本字段具有由自动布局指定的零宽度。

如何为文本字段的fittingSizeintrinsicContentSize属性获取有意义的值,以便它们反映文本字段的内容?

3 个答案:

答案 0 :(得分:6)

在不使用fittingSize的情况下计算文本字段最佳宽度的另一种方法是使用以下代码(替换John Sauer的sizeTextFieldWidthToFit方法):

- (void) sizeTextFieldWidthToFit {
    [textField sizeToFit];
    CGFloat newWidth = NSWidth(textField.frame);
    textFieldWidthConstraint.constant = newWidth;
}

您可以将textFieldWidthConstraint的优先级设置为低于另一个不等式约束的优先级,将您的要求表示为最小值25。

答案 1 :(得分:2)

我无法解释为什么NSTextField的intrinsicContentSize的宽度为-1,但我能够根据其attributesString的大小计算出一个。这是我创建NSTextField的方式:

// textField is an instance variable.
textField = [NSTextField new] ;
textField.translatesAutoresizingMaskIntoConstraints = NO ;
[view addSubview:textField] ;

NSDictionary* viewsDict = NSDictionaryOfVariableBindings(view, textField) ;
// textFieldWidthConstraint is an instance variable.
textFieldWidthConstraint  = [NSLayoutConstraint constraintsWithVisualFormat:@"H:[textField(==0)]"  options:0  metrics:nil  views:viewsDict] [0] ;
[view addConstraint:textFieldWidthConstraint] ;
NSNumber* intrinsicHeight = @( textField.intrinsicContentSize.height ) ;
[view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[textField(==intrinsicHeight)]"  options:0  metrics:NSDictionaryOfVariableBindings(intrinsicHeight)  views:viewsDict]] ;

// Position textField however you like.
[view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[textField]"  options:0  metrics:nil  views:viewsDict]] ;
[view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[textField]"  options:0  metrics:nil  views:viewsDict]] ;

[self sizeTextFieldWidthToFit] ;
// set textField's delegate so that  sizeTextFieldWidthToFit  is called when textField's text changes.
textField.delegate = self ;

以下是在文本更改时调整大小的方法:

- (void) controlTextDidChange:(NSNotification*)aNotification {
    if ( aNotification.object == textField )
        [self sizeTextFieldWidthToFit] ;
}

- (void) sizeTextFieldWidthToFit {
    // I'd like the width to always be >= 25.
    CGFloat newWidth = 25 ;
    if ( ! [textField.stringValue isEqualToString:@""] ) {
        NSDictionary* attributes = [textField.attributedStringValue  attributesAtIndex:0  effectiveRange:nil] ;
        NSSize size = [textField.stringValue sizeWithAttributes:attributes] ;
        newWidth =  MAX(newWidth, size.width + 10) ;
    }
    textFieldWidthConstraint.constant  = newWidth  ;
}

答案 2 :(得分:0)

我在这里添加这个是因为这些答案都很老了,我找不到让NSTextField在一个答案中使用autolayout和NSConstraints自动换行和播放所需的一切。

使用这些设置,文本将:

  • 保留在约束设置的水平边界内。
  • 自动换行字边界。
  • 根据需要自动调整高度。
  • 按下下面的任何内容(如果附加约束)。

这是让它正常工作的代码:

NSTextField *instructions = [NSTextField labelWithString:@"Some very long text..."];
instructions.translatesAutoresizingMaskIntoConstraints = NO;
instructions.autoresizesSubviews = YES;
instructions.usesSingleLineMode = NO;
instructions.lineBreakMode = NSLineBreakByWordWrapping;
[instructions cell].wraps = YES;
[instructions cell].scrollable = NO;
instructions.maximumNumberOfLines = 10;
instructions.preferredMaxLayoutWidth = 400.0;
[self addSubview:iCloudInstructions];

[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[instructions]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(instructions)]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[instructions]-(20)-[button]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(instructions, instructions)]];