如何在矩形中最佳地拟合NSString?

时间:2010-12-29 00:27:30

标签: cocoa macos nsstring

  

可能重复:
  Change NSTextField font size to fit

我试图在给定的矩形内拟合一个可变长度的字符串(字符串中的单词数是未知的)。我想最好地调整字符串的大小,使其尽可能大,并适合矩形。此外,如果有多个单词并且单词不应在多行上部分呈现,则字符串应该自动换行。我的问题有时是一个单词部分布局在多行上,如下所示。关于我可能做错什么的任何建议?

谢谢。

alt text

我正在使用NSLayoutManager,NSTextStorage和NSTextContainer。

我按如下方式初始化所有内容:

    textStorage = [[NSTextStorage alloc] initWithString:@""];
    layoutManager = [[NSLayoutManager alloc] init];
    textContainer = [[NSTextContainer alloc] init];

    [layoutManager addTextContainer:textContainer];     
    [textStorage addLayoutManager:layoutManager];   

    paraStyle = [[NSMutableParagraphStyle alloc] init];
    [paraStyle setLineBreakMode:NSLineBreakByWordWrapping];
    [paraStyle setParagraphStyle:[NSParagraphStyle defaultParagraphStyle]];
    [paraStyle setAlignment:NSCenterTextAlignment];
然后我按如下方式计算字体大小,

- (float)calculateFontSizeForString:(NSString *)aString andBoxSize:(NSSize)aBox
{
    //Create the attributed string
    NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:aString];
    [textStorage setAttributedString:attrString];
    [textContainer setContainerSize:NSMakeSize(aBox.width, FLT_MAX)];   
    [attrString release]; //Clean up

    //Initial values
    float fontSize = 50.0;
    float fontStepSize = 100.0;
    NSRect stringRect;
    BOOL didFindHeight = NO;
    BOOL shouldIncreaseHeight = YES;

    while (!didFindHeight)
    {   
        NSMutableDictionary *stringAttributes = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                                 paraStyle, NSParagraphStyleAttributeName,
                                                 [NSFont systemFontOfSize:fontSize], NSFontAttributeName, nil];

        [textStorage addAttributes:stringAttributes range:NSMakeRange(0, [textStorage length])];

        (void)[layoutManager glyphRangeForTextContainer:textContainer];     
        stringRect = [layoutManager usedRectForTextContainer:textContainer];

        if (shouldIncreaseHeight)
        {
            if (stringRect.size.height > aBox.height)
            {
                shouldIncreaseHeight = NO;
                fontStepSize = fontStepSize/2;
            }

            fontSize += fontStepSize;
        }
        else
        {
            if (stringRect.size.height < aBox.height)
            {
                shouldIncreaseHeight = YES;

                fontStepSize = fontStepSize/2;

                if (fontStepSize <= 0.5)
                {
                    didFindHeight = YES;
                }
            }

            if ((fontSize - fontStepSize) <= 0)
            {
                fontStepSize = fontStepSize/2;              
            }
            else
            {
                fontSize -= fontStepSize;
            }
        }
    }

    return fontSize;
}

1 个答案:

答案 0 :(得分:1)

请在发布前进行搜索。这反复出现。最新答案是here,但我认为其他地方的代码列表有更完整的答案。

我公认的简单示例显示了如何在没有文本容器和布局管理器的情况下执行此操作,但您的方法更加强大。不幸的是,蛮力(尺寸调整直到它适合)是确定最佳配合的唯一方法。