根据 Font/Size 改变 NSTextField 的高度

Posted

技术标签:

【中文标题】根据 Font/Size 改变 NSTextField 的高度【英文标题】:Change NSTextField's height according to Font/Size 【发布时间】:2012-10-22 11:15:04 【问题描述】:

好的,这是我的情况:

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

问题:

根据使用的字体和大小,文本的底部会丢失(因为它超出了NSTextField 的边界

我想要什么:

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

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

有什么想法吗?有什么可以指点我的吗?

【问题讨论】:

【参考方案1】:

如前所述,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

【讨论】:

【参考方案2】:

正如@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 所说的那样。

【讨论】:

【参考方案3】:

你可以取字符串的大小,然后相应地改变高度

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];

【讨论】:

这(我的意思是它的等价物)对 OS X 也有效吗? 好的,谢谢哥们!给我一分钟看看这个,我会告诉你... 当然..检查n让我知道..如果这不起作用,我们可以想出别的办法 sizeWithFont 仅适用于 UIKit,在 AppKit 中您应该使用 boundingRectWithSize。在这里查看答案:***.com/questions/5033598/… 这个答案不应该被标记为正确 - NSTextField 与 UITextField 不同。有关适用于 NSTextField 的内容,请参阅上面链接的 Scott 的答案。

以上是关于根据 Font/Size 改变 NSTextField 的高度的主要内容,如果未能解决你的问题,请参考以下文章

怎么让label的文字大小随label宽高改变大小? C# winform

sass中px转rem单位

怎么让label的文字大小随label宽高改变大小? C# winform

用 php 将每个 font size="" 替换为 font-size: ;如何? [关闭]

css font size 最小值

如何改变label字体的大小