我正在创建将文本放在图像顶部的东西。后端指定了允许绘制的最大文本框,我必须尽力适应用户在该矩形中输入的任何文本。
我查找了很多旧答案,但是所有答案似乎要么使用UILabel
自动拟合,要么仅使用强行强制String.boundingRect(with:options:attributes:context:)
。
我的最初想法是仅将文本矩形的高度用作点大小,但是除了不支持水平方向上太长的文本外,这似乎无法100%起作用。
这是我现在正在绘制内容的方式,只是为了获得一些背景信息。
let image = renderer.image { context in
backgroundImage.draw(at: .zero)
let titleAttributes: [NSAttributedStringKey: Any] = [
.font: UIFont(name: fontName, size: maxSize.height)!,
.foregroundColor: UIColor.white,
.paragraphStyle: NSMutableParagraphStyle(alignment: alignment),
.shadow: NSShadow( color: .black, offset: .zero, radius: 28),
]
(title as NSString).draw(with: maxFrame,
options: .usesLineFragmentOrigin,
attributes: titleAttributes,
context: nil)
}
有没有一种有效的方法可以计算出字体的点大小以适合矩形,而无需使用UILabel或强行使用它?
答案 0 :(得分:2)
我自己又解决了!
我正在绘制的文本不允许换行,因此始终为一行。在Playgrounds中制作暴力破解方法时,我注意到文本宽度与字体大小成线性关系。这样就很容易。
extension UIFont {
convenience init?(named fontName: String, fitting text: String, into targetSize: CGSize, with attributes: [NSAttributedStringKey: Any], options: NSStringDrawingOptions) {
var attributes = attributes
let fontSize = targetSize.height
attributes[.font] = UIFont(name: fontName, size: fontSize)
let size = text.boundingRect(with: CGSize(width: .greatestFiniteMagnitude, height: fontSize),
options: options,
attributes: attributes,
context: nil).size
let heightSize = targetSize.height / (size.height / fontSize)
let widthSize = targetSize.width / (size.width / fontSize)
self.init(name: fontName, size: min(heightSize, widthSize))
}
}
此扩展名将启动一种字体,该字体可以保证在目标矩形内,只要为1行即可。