NSString特定于帧宽度的字体大小

use*_*092 3 objective-c nsstring drawrect sizewithfont

drawRect用于文本显示,打电话NSString.我正在尝试使用sizeWithFont默认字体大小为17自动调整字体大小(缩小)并使用循环将字体大小减小1,如果它不适合宽度的大小.任何人都可以帮我解决这个问题吗?现在示例很好我只需要将字体大小设置为17.0

[[self.string displayName] drawAtPoint:CGPointMake(xcoord, ycoord) withFont:[UIFont boldSystemFontOfSize:17.0]];
CGSize size = [[self.patient displayName] sizeWithFont:[UIFont boldSystemFontOfSize:17.0]];
max_current_y = size.height > max_current_y ? size.height : max_current_y;
xcoord = xcoord + 3.0f + size.width;
Run Code Online (Sandbox Code Playgroud)

pur*_*020 12

好吧,那算了.这是使用NSString返回字体的相同方法的修改版本:

    -(UIFont*)getFontForString:(NSString*)string
               toFitInRect:(CGRect)rect
                  seedFont:(UIFont*)seedFont{
    UIFont* returnFont = seedFont;
    CGSize stringSize = [string sizeWithAttributes:@{NSFontAttributeName : seedFont}];

    while(stringSize.width > rect.size.width){
        returnFont = [UIFont systemFontOfSize:returnFont.pointSize -1];
        stringSize = [string sizeWithAttributes:@{NSFontAttributeName : returnFont}];
    }

    return returnFont;
}
Run Code Online (Sandbox Code Playgroud)

以下是如何调用它:

NSString* stringToDraw = @"Test 123";

    CGRect rect = CGRectMake(100., 100., 100., 200.);
    UIFont* font = [self getFontForString:stringToDraw toFitInRect:rect seedFont:[UIFont systemFontOfSize:20]];
    [stringToDraw drawInRect:rect withFont:font];
Run Code Online (Sandbox Code Playgroud)

代码适用于iOS7 +


ham*_*ene 9

尝试使用步骤1.0的字体大小可能非常慢.您可以通过对两种不同尺寸进行两种测量来极大地改进算法,然后使用线性近似来猜测非常接近正确尺寸的尺寸.

如果结果不够接近,请使用猜测的大小而不是前两个中的一个重复计算,直到它足够好或停止更改为止:

// any values will do, prefer those near expected min and max
CGFloat size1 = 12.0, size2 = 56.0; 
CGFloat width1 = measure_for_size(size1);
CGFloat width2 = measure_for_size(size2);

while (1) {
    CGFloat guessed_size = size1 + (required_width - width1) * (size2 - size1) / (width2 - width1);

    width2 = measure_for_size(guessed_size);
    if ( fabs(guessed_size-size2) < some_epsilon || !is_close_enough(width2, required_width) ) {
        size2 = guessed_size;
        continue;
    }
    // round down to integer and clamp guessed_size as appropriate for your design
    return floor(clamp(guessed_size, 6.0, 24.0));
}
Run Code Online (Sandbox Code Playgroud)

is_close_enough()实施完全取决于你.鉴于文本宽度几乎与字体大小呈线性增长,您可以简单地删除它,只需进行2-4次迭代即可.

  • 这是一个比接受答案的强力搜索更好的解决方案.值得注意的是,从iOS 7.0开始,不推荐使用`sizeWithFont:`.替换调用`sizeWithAttributes:`对于像这样的搜索来说是一个重大改进,因为它返回了确切的未包含大小. (2认同)

jow*_*wie 5

我想尝试制作一个不需要使用do ... while循环重复检查字体大小的版本.相反,我假设字体点大小是线性比例,然后计算出所需帧宽和实际帧宽之间的大小差异,然后相应地调整字体大小.因此,我最终得到了这个功能:

+ (CGFloat)fontSizeToFitString:(NSString *)string inWidth:(float)width withFont:(UIFont *)font
{
    UILabel *label = [UILabel new];
    label.font = font;
    label.text = string;
    [label sizeToFit];

    float ratio = width / label.frame.size.width;
    return font.pointSize * ratio;
}
Run Code Online (Sandbox Code Playgroud)

传入任何大小的字体,字符串和所需的宽度,它将返回该字体的磅值.

我还想更进一步,找出多行字符串的字体大小,以便最长的行适合没有换行符:

+ (CGFloat)fontSizeToFitLongestLineOfString:(NSString *)string inWidth:(float)width withFont:(UIFont *)font
{
    NSArray *stringLines = [string componentsSeparatedByString:@"\n"];

    UILabel *label = [UILabel new];
    label.font = font;

    float maxWidth = 0;

    for(NSString *line in stringLines)
    {
        label.text = line;
        [label sizeToFit];
        maxWidth = MAX(maxWidth, label.frame.size.width);
    }

    float ratio = width / maxWidth;
    return font.pointSize * ratio;
}
Run Code Online (Sandbox Code Playgroud)

似乎对我来说完全没问题.希望它可以帮助别人.