ios - 如何使 NSStringDrawingContext 缩小文本?

标签 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 的文档或在线资源很少。而且我试图避免使用 sizeWithFont:minFontSize:actualFontSize:forWidth:lineBreakMode: ,它在 iOS 7 中已被弃用。

最佳答案

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 的这个特性现在没有用了。我无法判断这是错误还是该功能已被故意放弃。

关于ios - 如何使 NSStringDrawingContext 缩小文本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17633032/

相关文章:

ios - 如何使用蓝牙信号 (BLE) 唤醒 iOS 应用程序

ios - 无法使用方法 swizzling 打印当前的 ViewController 名称

ios - 根据他子tableview在SWIFT中的高度调整scrollview的高度

jquery - 在元素中查找文本字符串并在其周围包裹一些 span 标签

ios - 多行文本没有被省略

android - 在 flutter 形式的 sqlite 数据库的 ListView 中加载 7000 多个项目的内存有效方法是什么

python - 在Python中对20个新闻组数据集进行排序

python - 假设我有 2 个向量。我可以使用什么算法来比较它们?

cocoa - NSTextField 的属性字符串渲染延迟

ios - 如何清除 NSMutableAttributedString 中的属性?