16

我正在尝试使用 iOS 6 的属性字符串 API 来计算文本的大小并在必要时缩小字体大小。但是,我无法像文档中所说的那样让它工作。

NSString *string = @"This is a long text that doesn't shrink as it should";

NSStringDrawingContext *context = [NSStringDrawingContext new];
context.minimumScaleFactor = 0.5;

UIFont *font = [UIFont fontWithName:@"SourceSansPro-Bold" size:32.f];

NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
paragraphStyle.lineBreakMode = NSLineBreakByClipping;

NSDictionary *attributes = @{ NSFontAttributeName: font,
                              NSParagraphStyleAttributeName: paragraphStyle };

NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:self.title attributes:attributes];

CGRect rect = [attributedString boundingRectWithSize:CGSizeMake(512.f, 512.f) options:NSStringDrawingUsesLineFragmentOrigin context:context];

NSLog(@"rect: %@, context: %@", NSStringFromCGRect(rect), context.debugDescription);

但文本不会缩小并被截断。actualScaleFactor总是1。日志结果如下:

rect:{{0, 0}, {431.64801, 80.447998}}, context:<NSStringDrawingContext: 0x14e85770> minimumScaleFactor:0.500000 minimumTrackingAdjustment:0.000000 actualScaleFactor:1.000000 actualTrackingAdjustment:0.000000 totalBounds:{{0, 0}, {431.64801, 80.447998}}

如果我使用实际绘图方法而不是测量方法,结果是相同的。如果我删除段落样式,它会使文本换行并且不会缩小它。如果我删除段落样式并选择只允许一行文本的大小,则文本也会被截断而不是缩小。怎么了?很少有文档或在线资源处理NSStringDrawingContext. 而且我试图避免使用sizeWithFont:minFontSize:actualFontSize:forWidth:lineBreakMode:iOS 7 中已弃用的内容。

4

3 回答 3

10

NSStringDrawingContext's minimumScaleFactor appears to be broken in iOS 7.

As far as I can make out, even in iOS 6, it didn't work for drawing; it worked for measuring, so you could work out what would happen in a context where it does work for drawing, like a UILabel. That way, you know the correct minimum height for the label.

Or, you could use the resulting scale factor to shrink the text yourself, in the knowledge that now it will fit.

Example:

- (void)drawRect:(CGRect)rect
{
    // rect is 0,0,210,31

    NSMutableAttributedString* s = 
        [[NSMutableAttributedString alloc] initWithString: @"This is the army Mister Jones."];
    [s addAttributes:@{NSFontAttributeName:[UIFont fontWithName:@"GillSans" size:20]} 
        range:NSMakeRange(0,s.length)];

    NSMutableParagraphStyle* para = [[NSMutableParagraphStyle alloc] init];
    para.lineBreakMode = NSLineBreakByTruncatingTail;
    [s addAttributes:@{NSParagraphStyleAttributeName:para} 
        range:NSMakeRange(0,s.length)];

    NSStringDrawingContext* con = [[NSStringDrawingContext alloc] init];
    con.minimumScaleFactor = 0.5;

    CGRect result = 
        [s boundingRectWithSize:rect.size 
            options:NSStringDrawingUsesLineFragmentOrigin context:con];
    CGFloat scale = con.actualScaleFactor;
    // ...(could have a check here to see if result fits in target rect)...

    // fix font to use scale factor, and draw
    [s addAttributes:@{NSFontAttributeName:[UIFont fontWithName:@"GillSans" size:20*scale]} 
        range:NSMakeRange(0,s.length)];
    [s drawWithRect:rect options:NSStringDrawingUsesLineFragmentOrigin context:nil];

}

In iOS 6, scale is about 0.85 and you can use it as shown to shrink the text. But in iOS 7, scale remains at 1, suggesting that no shrinkage is happening and this feature of NSStringDrawingContext is now useless. I can't tell whether that's a bug or whether the feature has been deliberately abandoned.

于 2013-10-23T05:43:40.583 回答
5

谷歌搜索了很长时间后,我没有找到在 iOS7 下工作的解决方案。现在我使用以下解决方法,知道它非常难看。我在内存中渲染一个 UILabel,截屏并绘制它。UILabel 能够正确缩小文本。

但也许有人觉得它有用。

    UILabel *myLabel = [[UILabel alloc] initWithFrame:myLabelFrame];
    myLabel.font = [UIFont fontWithName:@"HelveticaNeue-BoldItalic" size:16];
    myLabel.text = @"Some text that is too long";
    myLabel.minimumScaleFactor = 0.5;
    myLabel.adjustsFontSizeToFitWidth = YES;
    myLabel.backgroundColor = [UIColor clearColor];

    UIGraphicsBeginImageContextWithOptions(myLabelFrame.size, NO, 0.0f);
    [[myLabel layer] renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    [screenshot drawInRect:myLabel.frame];
于 2014-02-09T22:09:43.587 回答
0

只是想发布这个解决方案,因为我已经为此奋斗了几个小时。我永远无法缩小文本区域,并且总是会切断最后几行文本。

我的解决方案是不添加上下文,只需将其设置为 nil。我在查看此站点上的示例时得到了这个。https://littlebitesofcocoa.com/144-drawing-multiline-strings

请注意,在获取框将绘制的大小后使用

pageStringSize = [myString boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:attrsDictionary context:nil];

我仍然需要手动循环缩小字体:

while (pageStringSize.size.height > 140 && scale > 0.5) {
            scale = scale - 0.1;
            font = [UIFont fontWithName:@"Chalkboard SE" size:24.0 *scale];
            attrsDictionary = [NSDictionary dictionaryWithObjectsAndKeys:font, NSFontAttributeName,[NSNumber numberWithFloat:1.0], NSBaselineOffsetAttributeName, nil];

            pageStringSize = [myString boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:attrsDictionary context:nil];

        }
于 2017-01-07T02:41:48.443 回答