前言
在日常开发当中总免不了计算label的高度以及显示行数,下面分享一下Swift的写法。
一、行数
1、为UILabel创建一个扩展处理
UILabel+FormattedText
extension UILabel {
//计算label的行数
func getRealLabelTextLines() -> Int {
guard let labelText = text else {
return 0
}
//计算理论上显示所有文字需要的尺寸
let rect = CGSize(width: self.bounds.width, height: CGFloat.greatestFiniteMagnitude)
let labelTextSize = (labelText as NSString)
.boundingRect(with: rect, options: .usesFontLeading,attributes: [NSAttributedString.Key.font: self.font!], context: nil)
//计算理论上需要的行数
let labelTextLines = Int(ceil(CGFloat(labelTextSize.height) / self.font.lineHeight))
return labelTextLines
}
}
注意:计算行数的时候一定要用.usesFontLeading
注意:如果用自动布局,那么选调用self.layoutIfNeeded()方法再去获取label的行数和高度
2、关于NSStringDrawingOptions解释
public struct NSStringDrawingOptions : OptionSet {
public init(rawValue: Int)
public static var usesLineFragmentOrigin: NSStringDrawingOptions { get }
public static var usesFontLeading: NSStringDrawingOptions { get }
public static var usesDeviceMetrics: NSStringDrawingOptions { get }
@available(iOS 6.0, *)
public static var truncatesLastVisibleLine: NSStringDrawingOptions { get }
}
计算高度传入
[.usesFontLeading,.usesLineFragmentOrigin]
计算行数的时候传入:
.usesFontLeading
二、高度
1、根据宽度求高度
func getRealLabelTextHeight() -> CGFloat {
guard let labelText = text else {
return 0
}
//计算理论上显示所有文字需要的尺寸
let rect = CGSize(width: self.bounds.width, height: CGFloat.greatestFiniteMagnitude)
let labelTextSize = (labelText as NSString)
.boundingRect(with: rect, options: [.usesFontLeading,.usesLineFragmentOrigin],attributes: [NSAttributedString.Key.font: self.font!], context: nil)
return labelTextSize.height
}
2、判断文本标签的内容是否被截断
//判断文本标签的内容是否被截断
var isTruncated: Bool {
guard let labelText = text else {
return false
}
//计算理论上显示所有文字需要的尺寸
let rect = CGSize(width: self.bounds.width, height: CGFloat.greatestFiniteMagnitude)
let labelTextSize = (labelText as NSString)
.boundingRect(with: rect, options: .usesLineFragmentOrigin,
attributes: [NSAttributedString.Key.font: self.font!], context: nil)
//计算理论上需要的行数
let labelTextLines = Int(ceil(CGFloat(labelTextSize.height) / self.font.lineHeight))
//实际可显示的行数
var labelShowLines = Int(floor(CGFloat(bounds.size.height) / self.font.lineHeight))
if self.numberOfLines != 0 {
labelShowLines = min(labelShowLines, self.numberOfLines)
}
//比较两个行数来判断是否需要截断
return labelTextLines > labelShowLines
}
三、关于boundingRect计算不准问题
1、前面提到使用boundingRect方法的时候需要注意选择类型,之前同事写的代码就是没注意这个,造成计算行数不对,具体代码如下:
明显labelTextSize与label本身的宽度相差9个像素,造成本来是三行的文字返回了四行。
使用.usesFontLeading后计算正确了
END.