iOS_Swift 实现UITextView,显示前n行,点击显示“更多”,再点击“收起”效果

2022-07-20 14:32:41 浏览数 (1)

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每行显示的文字

0 人点赞