根据字体/大小更改NSTextField的高度

时间:2012-10-22 11:15:05

标签: objective-c cocoa size nstextfield nsfont

好的,这是我的情况:

  • 我有一个NSTextField,设置为多行文字标签
  • NSTextField应该只包含一行文字(即使它是多行文字)
  • NSTextField固定高度
  • 用户更改字体字体大小

问题:

  • 根据所使用的字体和尺寸,文字的底部缺失(因为它超出了NSTextField的边界

我想要的是什么:

  • 根据选择(字体和字体大小)获取文字高度,并相应地设置NSTextField的高度。

我知道这可能听起来很复杂,但我也知道可以做到。

有什么想法吗?有什么参考指向我吗?

3 个答案:

答案 0 :(得分:4)

如前所述,NSTextField和UITextField是非常不同的对象(与他们的名字相反)。具体来说,对于NSTextField,您可以使用涉及NSLayoutManager的优雅解决方案。 NSLayoutManager对象协调NSTextStorage对象中保存的字符的布局和显示。它将Unicode字符代码映射到字形,在一系列NSTextContainer对象中设置字形,并将它们显示在一系列NSTextView对象中。

您需要的只是创建一个NSLayoutManager,一个NSTextContainer和一个NSTextStorage。它们以类似的方式包装在一起:

.-----------------------.
|     NSTextStorage     | 
|  .-----------------.  |
|  | NSLayoutManager |  |
|  '-----------------'  |
|  | NSTextStorage   |  |
|  '-----------------'  |
|                       |
'-----------------------'

也就是说,您可以使用layoutManager方法usedRectForTextContainer:估算包含所需文本的正确大小。

以下内容适用于您的问题:

- (float)heightForStringDrawing:(NSString *)aString withFont:(NSFont *)aFont andWitdh:(float)myWidth
{
    NSTextStorage *textStorage = [[NSTextStorage alloc] initWithString:aString];
    NSTextContainer *textContainer = [[NSTextContainer alloc] initWithContainerSize:NSMakeSize(myWidth,CGFLOAT_MAX)];

    NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
    [layoutManager setTypesetterBehavior:NSTypesetterBehavior_10_2_WithCompatibility];
    [layoutManager addTextContainer:textContainer];
    [textStorage addLayoutManager:layoutManager];

    [textStorage addAttribute:NSFontAttributeName value:aFont
                        range:NSMakeRange(0,[textStorage length])];
    [textContainer setLineFragmentPadding:0.0];

    NSRange glyphRange = [layoutManager glyphRangeForTextContainer:textContainer];
    [layoutManager drawGlyphsForGlyphRange: glyphRange atPoint:NSMakePoint(0, 0)];

    return [layoutManager usedRectForTextContainer:textContainer].size.height;
}

有关此主题的详尽Apple文档:

https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/TextLayout/Tasks/StringHeight.html#//apple_ref/doc/uid/20001809-CJBGBIBB

此外,一些退伍军人早些时候在Apple Mailing List上解决了这个问题:

http://lists.apple.com/archives/cocoa-dev/2006/Jan/msg01874.html

答案 1 :(得分:1)

正如@valvoline所说,这是可行的,但是如果在drawRect之外执行此操作,则会收到许多CGContext警告,例如CGContextGetFontRenderingStyle: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.。最好的解决方案是不使用drawGlyphsForGlyphRange:正如苹果文档https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/TextLayout/Tasks/StringHeight.html#//apple_ref/doc/uid/20001809-CJBGBIBB所言。

答案 2 :(得分:-2)

您可以获取字符串的大小,然后相应地更改高度

NSString *text = // your string
CGSize constraint = CGSizeMake(210, 20000.0f);
CGSize size = [text sizeWithFont:[UIFont fontWithName:@"Helvetica-Light" size:14] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];

UITextField *cellTextLabel = [[UITextField alloc] initWithFrame:CGRectMake(70, 9, 230, size.height)];
cellTextLabel.lineBreakMode = UILineBreakModeWordWrap;
cellTextLabel.numberOfLines = 50;
cellTextLabel.backgroundColor = [UIColor clearColor];
cellTextLabel.text = text;
cellTextLabel.font = [UIFont fontWithName:@"HelveticaNeue-Light" size:14];
[self.view addSubview:cellTextLabel];
[cellTextLabel release];