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

MOAttributedTextView

仅一个类Class实现:显示前n行文案,点击展开,再点击收起效果。继承自UITextView,运用NSMutableAttributedString实现

1、Effect display

Test1:直接使用效果如下:

在这里插入图片描述


Test2:在TableViewCell里使用效果如下:

在这里插入图片描述


2、核心代码:

// 行高
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每行显示的文字 这篇文章里找到解决方案)

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:

// 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 MOOFoldTextView

参考:

iOS 富文本添加点击事件

Ranges in Swift explained with code examples

ios获取UILabel每行显示的文字

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

莫小言mo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值