在iOS开发中,UILabel本身没有直接提供"最大字体"的属性,但可以通过以下几种方式实现字体大小的上限控制:
一、手动计算并设置字体大小
在设置文本后,根据文本内容和可用空间动态计算合适的字体大小,确保不超过预设的最大值:
swift
func adjustFontSize(for label: UILabel, maxFontSize: CGFloat) {
let originalFont = label.font
var fontSize = maxFontSize
// 逐步减小字体大小,直到文本适应标签宽度
while fontSize > 10 { // 设置最小字体限制
let testFont = UIFont(descriptor: originalFont.fontDescriptor, size: fontSize)
let attributes = [NSAttributedString.Key.font: testFont]
let textSize = label.text?.size(withAttributes: attributes) ?? .zero
if textSize.width <= label.bounds.width {
label.font = testFont
return
}
fontSize -= 1
}
// 如果减小到最小值仍不适应,使用最小字体
label.font = UIFont(descriptor: originalFont.fontDescriptor, size: 10)
}
// 使用示例
label.text = "这是一段可能需要调整字体大小的长文本"
adjustFontSize(for: label, maxFontSize: 24) // 最大字体为24pt
二、使用iOS 14+的Proportional Font Scaling
iOS 14引入了UIFontMetrics
的scaledFont(for:maximumPointSize:)
方法,可以自动缩放字体并设置上限:
swift
// 设置最大字体大小(例如24pt)
let maxFontSize: CGFloat = 24
let font = UIFont.systemFont(ofSize: 17) // 基础字体大小
// 自动缩放字体,同时限制最大尺寸
label.font = UIFontMetrics.default.scaledFont(for: font, maximumPointSize: maxFontSize)
// 确保支持动态类型(用户字体大小偏好)
label.adjustsFontForContentSizeCategory = true
三、使用UILabel的adjustsFontSizeToFitWidth
如果只需要在单行文本超出宽度时缩小字体,可以启用adjustsFontSizeToFitWidth
,并结合minimumScaleFactor
设置最小缩放比例:
swift
label.adjustsFontSizeToFitWidth = true // 自动缩小字体以适应宽度
label.minimumScaleFactor = 0.5 // 最小缩放至原字体的50%
label.numberOfLines = 1 // 确保单行显示
// 设置字体,例如最大为24pt
let originalFont = UIFont.systemFont(ofSize: 24)
label.font = originalFont
这种方法的局限性在于:
- 只能缩小不能放大(如果文本很短,字体不会超过原始大小)。
- 只处理宽度,不处理高度(多行文本时可能需要结合其他方法)。
四、自定义UILabel子类
封装上述逻辑到自定义UILabel子类中,便于复用:
swift
class BoundedSizeLabel: UILabel {
var maxFontSize: CGFloat = 24
override func layoutSubviews() {
super.layoutSubviews()
adjustFontSize()
}
private func adjustFontSize() {
guard let text = text, let currentFont = font else { return }
// 使用UIFontMetrics计算适合的字体大小
let scaledFont = UIFontMetrics.default.scaledFont(for: currentFont)
let constraintRect = CGSize(width: bounds.width, height: .greatestFiniteMagnitude)
let boundingBox = text.boundingRect(
with: constraintRect,
options: [.usesLineFragmentOrigin, .usesFontLeading],
attributes: [.font: scaledFont],
context: nil
)
// 如果文本高度超过标签高度,逐步减小字体
if boundingBox.height > bounds.height {
var fontSize = scaledFont.pointSize
while fontSize > 10 && boundingBox.height > bounds.height {
fontSize -= 1
let smallerFont = UIFont(descriptor: currentFont.fontDescriptor, size: fontSize)
let smallerBoundingBox = text.boundingRect(
with: constraintRect,
options: [.usesLineFragmentOrigin, .usesFontLeading],
attributes: [.font: smallerFont],
context: nil
)
if smallerBoundingBox.height <= bounds.height || fontSize <= 10 {
font = smallerFont
break
}
}
} else if scaledFont.pointSize > maxFontSize {
// 如果计算出的字体超过最大值,使用最大值
font = UIFont(descriptor: currentFont.fontDescriptor, size: maxFontSize)
}
}
}
// 使用示例
let boundedLabel = BoundedSizeLabel()
boundedLabel.maxFontSize = 24
boundedLabel.text = "自定义最大字体的标签"
五、结合自动布局
如果使用自动布局,确保为UILabel设置了明确的宽度约束,否则自适应计算可能不准确:
swift
// 示例:设置UILabel最大宽度为父视图的80%
label.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20).isActive = true
label.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20).isActive = true
// 应用字体大小限制
label.font = UIFontMetrics.default.scaledFont(for: UIFont.systemFont(ofSize: 17), maximumPointSize: 24)
label.adjustsFontForContentSizeCategory = true
注意事项
- 多行文本:对于多行文本,需同时考虑宽度和高度的约束。
- 动态类型 :如果支持用户字体大小偏好(Dynamic Type),建议结合
UIFontMetrics
使用。 - 性能:频繁计算文本大小可能影响性能,建议在必要时调用(如文本变化或布局更新后)。
通过以上方法,你可以灵活控制UILabel的字体大小上限,确保文本在不同场景下都能正确显示。