如何使NSStringDrawingContext缩小文本?

时间:2013-07-13 18:27:32

标签: ios text nsattributedstring

我正在尝试使用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的文档或在线资源非常少。我试图避免使用在iOS 7中弃用的sizeWithFont:minFontSize:actualFontSize:forWidth:lineBreakMode:

3 个答案:

答案 0 :(得分:9)

NSStringDrawingContext的minimumScaleFactor似乎在iOS 7中被破坏了。

据我所知,即使在iOS 6中,它也无法用于绘图;它可以用于测量,因此您可以计算出在 工作的上下文中会发生什么,比如UILabel。这样,您就知道标签的正确最小高度。

或者,您可以使用生成的比例因子自行缩小文本,以了解现在适合的文本。

示例:

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

}

在iOS 6中,scale约为0.85,您可以如图所示缩小文本。但是在iOS 7中,scale保持为1,表明没有发生收缩,NSStringDrawingContext的这个功能现在没用了。我不知道这是一个错误,还是故意放弃了该功能。

答案 1 :(得分:4)

经过谷歌搜索很长一段时间后,我找不到在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];

答案 2 :(得分: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];

        }