首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >iOS_Swift 实现UITextView,显示前n行,点击显示“更多”,再点击“收起”效果

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

作者头像
mikimo
发布2022-07-20 14:32:41
发布2022-07-20 14:32:41
2.3K0
举报
文章被收录于专栏:iOS开发~iOS开发~

仅一个类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每行显示的文字

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-12-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、Effect display
  • 2、核心代码:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档