前言
UILabel显示文本非常出色,支持多行显示。但有的时候UI要求默认显示2-3行,点击展开后再收起。 实现这个功能原理都不复杂,很多的时候,项目一忙,就那么对付过去啦,比如使YYLable,非常方便的就能实现,就没有组件化。
ExpandLabel
An expandable/collapsible UILabel for iOS that supports text and images with no quantity limit. iOS 一个可展开/收起的UILabel,支持文字和图片,不限数量。
自定义展开,图文任意结合
自定义收起,图文任意结合
自定义展开/收起
功能特点
- 📝 支持多行文本自动截断和展开/收起功能
- 🎨 自定义展开/收起按钮的样式,支持文字和图片
- 🔄 支持点击事件处理
- 📱 兼容iOS 13+和macOS 10.15+
- 🎯 简单易用的API接口
安装
Swift Package Manager
在Xcode中,选择 File > Add Packages...,然后粘贴以下URL:
https://github.com/willlzq/ExpandLabel.git
点击 Add Package 按钮完成安装。
使用示例
基本用法
import UIKit
import ExpandLabel
class ViewController: UIViewController {
// 创建ExpandLabel实例
private lazy var expandLabel: ExpandLabel = {
let view = ExpandLabel()
// 基本配置
view.maxnumberOfLines = 3
view.backgroundColor = .clear
view.layer.cornerRadius = 5
view.layer.borderColor = UIColor.orange.cgColor
view.layer.borderWidth = 0.5
// 设置文本内容
let text = "Core Text是iOS 系统文本排版核心框架,TextKit和WebKit都是封装在CoreText上的,TextKit是iOS7引入的,在iOS7之前几乎所有的文本都是 WebKit 来处理的,包括UILable、UITextFileld等,TextKit是从Cocoa文本系统移植到iOS系统的。文本渲染过程中Core Text只负责排版,具体的绘制操作是通过Core Graphics框架完成的。如果需要精细的排版控制可以使用Core Text,否则可以直接使用Text Kit。"
let attributedText = NSAttributedString(string: text, attributes: [
.font: UIFont.systemFont(ofSize: 15),
.foregroundColor: UIColor.gray
])
view.attributedText = attributedText
// 设置展开和收起的样式
view.openToken = [
.text(title: " ... 展开 ", font: .boldSystemFont(ofSize: 15), foregroundColor: .blue)
]
view.closeToken = [
.text(title: " 收起 ", font: .boldSystemFont(ofSize: 15), foregroundColor: .blue)
]
// 应用设置
view.reload()
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
// 添加ExpandLabel到视图
view.addSubview(expandLabel)
// 设置约束
expandLabel.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
expandLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 15),
expandLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -15),
expandLabel.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20),
expandLabel.heightAnchor.constraint(greaterThanOrEqualToConstant: 100)
])
}
}
快速使用
let simpleLabel = ExpandLabel()
simpleLabel.maxnumberOfLines = 2
simpleLabel.attributedText = NSAttributedString(string: "这是一段可能会被截断的长文本内容,点击可以展开查看全部内容。")
simpleLabel.reload()
// 添加状态变化事件监听器
simpleLabel.addTarget(self, action: #selector(expandStateChanged(_:)), for: .expandStateChanged)
// 定义事件处理方法
@objc func expandStateChanged(_ sender: ExpandLabel) {
}
自定义展开/收起样式
支持自定义展开和收起按钮的样式,可以是文字、图片或两者的组合:
// 纯文本样式
expandLabel.openToken = [
.text(title: " [点击展开] ", font: .boldSystemFont(ofSize: 14), foregroundColor: .systemBlue)
]
expandLabel.closeToken = [
.text(title: " [点击收起] ", font: .boldSystemFont(ofSize: 14), foregroundColor: .systemBlue)
]
// 如果项目中有可用的图片资源,也可以使用带图片的样式
if let expandImage = UIImage(named: "expand_icon"),
let collapseImage = UIImage(named: "collapse_icon") {
expandLabel.openToken = [
.text(title: " 展开 ", font: .boldSystemFont(ofSize: 15), foregroundColor: .blue),
.image(icon: expandImage, size: CGSize(width: 16, height: 16), refrenceFont: .boldSystemFont(ofSize: 15))
]
expandLabel.closeToken = [
.text(title: " 收起 ", font: .boldSystemFont(ofSize: 15), foregroundColor: .blue),
.image(icon: collapseImage, size: CGSize(width: 16, height: 16), refrenceFont: .boldSystemFont(ofSize: 15))
]
}
关于内存释放
在Swift中使用Core Text等C API创建的对象(如framesetter,path,frame)不需要像Objective-C那样手动release。
Swift的自动引用计数(ARC)机制 :
- Swift会自动为Core Foundation对象管理内存,当对象超出作用域时自动释放
- 编译器会在适当的时机插入内存管理代码
Core Foundation内存管理桥接 :
- Swift为Core Foundation对象提供了自动内存管理桥接
- 大多数以 Create 、 Copy 等前缀创建的Core Foundation对象,在Swift中都会被自动管理
内存所有权转移 :
- 在Swift与Core Foundation交互时,Swift编译器会理解并尊重Core Foundation的内存管理规则
- 当使用从Core Foundation创建的对象时,Swift会接管其内存管理
与Objective-C的区别 :
- Objective-C中需要手动调用 CFRelease() 释放对象
- Swift通过编译器优化,自动处理了这些底层内存管理操作
注意事项
- 务必在设置完所有属性后调用
reload()方法,以应用设置。 - 如果文本内容较短,未达到最大行数限制,则不会显示展开/收起按钮。
- 在使用图片样式时,确保图片资源已正确添加到项目中。
- 如需监听展开/收起事件,可以通过添加点击事件处理来实现。