iOS7之后引入TextKit框架,能够很方便的可以通过方便的接口去修改文字的样式和排版,解决图文混排的问题。而在ios7之前解决起来都会比较的困难。
TextKit中有三个比较重要的对象
1、NSTextStorage,是NSMutableAttributedString的子类,专门用来存储文本的和管理控件的属性文本,NSTextStorage引用着NSLayoutManager,当NSTextStorage的属性发生变化时,会通知NSLayoutManager进行重新排版
2、NSLayoutManager专门用来管理文本布局的对象,定义布局方式,使文本内容按照一定的布局方式进行排版。NSLayoutManager引用着NSTextContainer,每次画内容的时候要根据NSTextContainer的大小来绘制
3、NSTextContainer,是一个容器,设定绘制的范围,定义排版区域。区域可以是圆形矩形,也可以定义不能填充的区域来显示非文本元素。
具体概念引用一下一句话:其实就是由NSLayoutManager从NSTextStorage中读取出文本数据,然后根据一定的排版方式,将文本排版到NSTextContainer中,再由NSTextContainer结合UITextView将最终效果显示出来。
这里说一下一般来说NSTextContainer的用途的话在layoutSubviews方法中设置下就可以了。
具体的应用
class TestLabel: UILabel {
//绘制文本
override func drawText(in rect: CGRect) {
//获取范围
let range = NSRange(location: 0, length: textStorage.length)
//绘制字形
layoutManager.drawGlyphs(forGlyphRange: range, at: CGPoint.zero)
}
override init(frame: CGRect) {
super.init(frame: frame)
prepare()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
prepare()
}
//准备文本的一些内容和关系
private func prepare()
{
//1、准备文本内容
prepareText()
//2、设置对象的关系
textStorage.addLayoutManager(layoutManager)
layoutManager.addTextContainer(textContainer)
}
private func prepareText()
{
//直接设置文本属性
if attributedText != nil
{
textStorage.setAttributedString(attributedText!)
}
else if text != nil
{
textStorage.setAttributedString(NSAttributedString(string:text!))
}
else
{
textStorage.setAttributedString(NSAttributedString(string: ""))
}
}
override func layoutSubviews() {
super.layoutSubviews()
//设置文本容器的尺寸
textContainer.size = bounds.size
}
//创建对象
//文本内容,是可变属性字符串的子类
private lazy var textStorage = NSTextStorage()
//布局管理器,负责文本绘制的
private lazy var layoutManager = NSLayoutManager()
//文本容器-设置绘制的尺寸
private lazy var textContainer = NSTextContainer()
}
效果图