IOS:如何计算要创建上下文的文本大小?

时间:2016-06-07 23:52:03

标签: ios objective-c swift cgcontext

我需要创建一个包含一行文本的图像。但问题是,我首先需要创建上下文(CGBitmapContextCreate),要求图像的宽度和高度有可能以后计算文本的边界(通过CTLineGetImageBounds)。但我想要图像的大小=文本的边界:(我该怎么办?

实际上我使用

CGBitmapContextCreate
CTLineGetImageBounds
CTLineDraw

也许可以在没有上下文的情况下调用CTLineGetImageBounds?

注意:我在delphi上,这不是一个真正的问题,因为我可以访问所有API,我只需要函数名称

6 个答案:

答案 0 :(得分:6)

您可以通过执行以下操作,根据要使用的字体计算NSString占用的空间:

NSString *testString = @"A test string";
CGSize boundingSize = self.bounds.size;
CGRect labelRect = [testString
                    boundingRectWithSize:boundingSize
                    options:NSStringDrawingUsesLineFragmentOrigin
                    attributes:@{ 
                        NSFontAttributeName : [UIFont systemFontOfSize:14]
                                }
                    context:nil];

其中边界大小是您希望图像的最大大小。然后,您可以使用计算的大小来创建图像。

答案 1 :(得分:3)

有几种方法可以计算或多或少精确的边界框。您可以使用字体指标,迭代CTRun或使用cocoa的字符串绘制API进行计算。

然而,我想提请你注意这个通常不可能的问题。虽然上述算法的结果在很多情况下已经足够,但有几种情况下它们是完全错误的:

  • 某些字母的部分远远超出字体中定义的指标。以下是Zapfino的一个例子:小写的变体" f"。 (绿色是文字编辑的选择)

Zapfino lower case f variation

  • 有一些效果超出了计算框。轮廓和阴影只是一个例子。阴影可以有很远的距离和巨大的模糊。

enter image description here

  • 您的算法可能不知道自定义文本属性。

  • 文字可以包含"附件" (像图像,我认为表情符号也作为附件实现)。这些也必须考虑在内。

当我不得不解决这个问题时,我终于达到了以下解决方案:

  1. 以最大尺寸创建透明位图上下文(在本例中为整页)。
  2. 在所需位置绘制文字。
  3. 从外到内遍历上下文中的字节,沿着每条边扫描第一个非透明像素。
  4. 使用CGImageCreateWithImageInRect剪切生成的矩形。
  5. 那个速度非常慢,但速度并不是我用例的优先考虑。

答案 2 :(得分:2)

好的,我找到了解决方案:使用CTLineGetImageBounds(aline,null {context});只需为上下文传递null,并按预期工作;)

答案 3 :(得分:2)

为了获得带有字体的文本大小,你需要编写。

let widthOfLabel = 400.0
let size = font?.sizeOfString(self.viewCenter.text!, constrainedToWidth: Double(widthOfLabel))

您必须使用以下字体扩展名才能获得带字体的文字大小。

extension UIFont {
    func sizeOfString (string: String, constrainedToWidth width: Double) -> CGSize {
        return NSString(string: string).boundingRectWithSize(CGSize(width: width, height: DBL_MAX),
                                                             options: NSStringDrawingOptions.UsesLineFragmentOrigin,
                                                             attributes: [NSFontAttributeName: self],
                                                             context: nil).size
    }
}

答案 4 :(得分:1)

下面的代码用于根据字体计算NSString Size

extension UIFont {
func sizeOfString (string: String, constrainedToWidth width: Double) -> CGSize {
    return NSString(string: string).boundingRectWithSize(CGSize(width: width, height: DBL_MAX),
        options: NSStringDrawingOptions.UsesLineFragmentOrigin,
        attributes: [NSFontAttributeName: self],
        context: nil).size
}
}

OR 或者,您可以将其转换为NSString

if let ns_str:NSString = str as NSString? {

let sizeOfString = ns_str.boundingRectWithSize(
                             CGSizeMake(self.titleLabel.frame.size.width, CGFloat.infinity), 
                             options: NSStringDrawingOptions.UsesLineFragmentOrigin, 
                             attributes: [NSFontAttributeName: lbl.font], 
                             context: nil).size
}

答案 5 :(得分:1)

听起来你已经完成了大部分工作。您只需要创建一个临时上下文来调用CTLineGetImageBounds。我相信这个上下文非常小(例如,一个像素,甚至可能为零),当然你可以重复使用它。理想情况下,它应该具有与最终上下文相同的属性(除了大小),尽管在大多数情况下这甚至可能都不重要。它只需要元数据。