需要cocopods引入YYKit
pod "YYKit"
代码中实现这个类,主要是靠YYKit获取每行有什么文案,然后拆成两个UILabel实现。
import UIKit
import YYKit
//最后一行文案留一段距离提前开始省略的文案view.
//定宽 高度自适应,需要指定最大行数和最后一行要预留提前省略的距离
class RightBottomSpaceLabelView : UIView {
private var label : UILabel = UILabel()
private var label2 : UILabel = UILabel()//展示最后一行
//调用后 本view的宽和高就定下来了.高度是最大行数或者文字行数,宽度为maxWidth
//lastLineSpace 是最后一行到右边的留空距离,如果文字行数没有达到最大行,此属性无效
func config(str:String,
font:UIFont,
textColor:UIColor,
maxWidth: CGFloat,
maxLines: Int,
lastLineSpace:CGFloat) {
label.numberOfLines = maxLines
label.textColor = textColor
label.font = font
label.isHidden = false
label2.numberOfLines = 1
label2.textColor = textColor
label2.font = font
label2.isHidden = false
let attributedString = NSMutableAttributedString(string: str)
attributedString.addAttributes([.font: font], range: attributedString.rangeOfAll())
let ranges = getLabelLinesRange(attributedText: attributedString, maxWidth: maxWidth)
if ranges.count <= 1 {
//只有一行
label.isHidden = true
label2.text = str
label2.sizeToFit()
if ranges.count < maxLines {
label2.width = maxWidth
}else{
label2.width = maxWidth - lastLineSpace
}
self.size = CGSize(width: maxWidth, height: label2.height)
}else{
//超过一行
if ranges.count < maxLines {
//没有达到最大行数
label2.isHidden = true
label.text = str
label.size = label.sizeThatFits(CGSize(width: maxWidth, height: CGFLOAT_MAX))
self.size = label.size
}else {
//超过或者刚好等于最大行数
let range = ranges[maxLines - 1]
let lastIndex = range.location
let firstStr = subString(str:str,fromIndex: 0, length: lastIndex)
label.text = firstStr
label.size = label.sizeThatFits(CGSize(width: maxWidth, height: CGFLOAT_MAX))
label2.top = label.height
let lastRange = ranges[maxLines - 1]
label2.text = subString(str:str,fromIndex: lastRange.location, length: str.count - lastRange.location)
label2.sizeToFit()
label2.width = maxWidth - lastLineSpace
self.size = CGSize(width: maxWidth, height: label2.bottom)
}
}
}
override init(frame: CGRect) {
super.init(frame: frame)
addSubview(label)
label.lineBreakMode = NSLineBreakMode.byTruncatingTail
addSubview(label2)
label2.lineBreakMode = NSLineBreakMode.byTruncatingTail
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
//获取每行文案的NSRange
private func getLabelLinesRange(attributedText: NSMutableAttributedString, maxWidth: CGFloat) -> [NSRange] {
var result: [NSRange] = []
let container = YYTextContainer(size: CGSize(width: maxWidth, height: CGFLOAT_MAX))
let layout = YYTextLayout(container: container, text: attributedText)
let lines = layout?.lines
for line in lines ?? [] {
result.append(line.range)
}
return result
}
private func subString (str:String,fromIndex:Int , length:Int) -> String? {
if(fromIndex >= str.count || fromIndex < 0 || length < 0){
return nil
}
if((fromIndex + length) > str.count || (fromIndex + length) < 0){
return nil
}
let startIndex = str.index(str.startIndex, offsetBy: fromIndex)
let endIndex = str.index(startIndex, offsetBy: length)
return String(str[startIndex..<endIndex])
}
}
在viewcontroller中简单的使用示例:
import YYKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let labelView = RightBottomSpaceLabelView()
labelView.config(str: "发的客户表示卡号轧空给对方关电脑发生的放松放松",
font: UIFont.systemFont(ofSize: 16),
textColor: .black,
maxWidth: 100,
maxLines: 3,
lastLineSpace: 50)
view.addSubview(labelView)
labelView.top = 100
}
}
示例效果: