MOAttributedTextView
仅一个类Class
实现:显示前n行文案,点击展开,再点击收起效果。继承自UITextView,运用NSMutableAttributedString实现
1、Effect display
Test1:直接使用效果如下:
Test2:在TableViewCell里使用效果如下:
2、核心代码:
代码语言:javascript复制// 行高
let lineHeight = lineSpacing font.lineHeight
// 整体高度
let rect = NSString(string: text closeText).boundingRect(with: CGSize(width: width-8, height: CGFloat.greatestFiniteMagnitude), options: .usesLineFragmentOrigin, attributes: [.font: font], context: nil)
let height = rect.height
// 整体行数
let allLine = Int(floor(height / font.lineHeight))
// 打开时的高度
let openHeight = CGFloat(allLine) * lineHeight
// 收起时的高度
var closeHeight = openHeight
if lessLine < allLine {
closeHeight = CGFloat(lessLine) * lineHeight
}
获得前n行的文案:(难点在此,差点放弃,最后在 ios获取UILabel每行显示的文字 这篇文章里找到解决方案)
代码语言:javascript复制let attributedString = NSMutableAttributedString(string: moAllText, attributes: moAttributs)
let ctFrameSetter = CTFramesetterCreateWithAttributedString(attributedString)
// here add 8 spacing to width for calculate
let containerFrame = CGRect(x: 0, y: 0, width: frame.size.width-8, height: CGFloat.greatestFiniteMagnitude)
let path = CGPath(rect: containerFrame, transform: nil)
let ctFrame = CTFramesetterCreateFrame(ctFrameSetter, CFRange(location: 0, length: 0), path, nil)
let lines: NSArray = CTFrameGetLines(ctFrame)
// length of the first less lines
var preLessLineLength = 0.0
for i in 0..<moLessLine {
let lineRange = CTLineGetStringRange(lines[i] as! CTLine)
preLessLineLength = Double(lineRange.length)
}
// get the first less lines of string
let index = moAllText.index(moAllText.startIndex, offsetBy: String.IndexDistance(preLessLineLength))
let preLessLineText = moAllText[...index]
设置AttributeString:
代码语言:javascript复制// cut the same text as openText, then openText
let startIndex = preLessLineText.index(preLessLineText.endIndex, offsetBy: -(moOpenText.count 2))
let endIndex = preLessLineText.endIndex
let range = startIndex ..< endIndex
let needShowText = preLessLineText.replacingCharacters(in: range, with: moOpenText)
// set attributs and pargrapgStyle for attributedString
let attributedString = NSMutableAttributedString(string: needShowText, attributes: moAttributs)
attributedString.addAttribute(.paragraphStyle, value: moParagraph, range: NSRange(location: 0, length: needShowText.count))
// add tap action for link range
let linkRange = NSRange(location: needShowText.count - moOpenText.count, length: moOpenText.count)
attributedString.addAttribute(.link, value: kMoClickUrlString, range: linkRange)
attributedText = attributedString
How to use and demo see here MOAttributedTextView
参考:
iOS 富文本添加点击事件
Ranges in Swift explained with code examples
ios获取UILabel每行显示的文字