第一步: 基础
实现下面的效果,注意到每一行的间距为 0

1,有这么一个富文本
let attributed = NSMutableAttributedString(string: "新丰美酒斗十千,咸阳游侠多少年。\n相逢意气为君饮,系马高楼垂柳边。\n出身仕汉羽林郎,初随骠骑战渔阳。\n孰知不向边庭苦,纵死犹闻侠骨香。");
attributed.addAttributes([NSAttributedString.Key.font: UIFont.systemFont(ofSize: 20)], range: NSMakeRange(0, attributed.length))
attributed.addAttributes([NSAttributedString.Key.font: UIFont.systemFont(ofSize: 30)], range: NSMakeRange(2, 2))
attributed.addAttributes([NSAttributedString.Key.foregroundColor: UIColor.orange], range: NSMakeRange(0, 7))
attributed.addAttributes([NSAttributedString.Key.foregroundColor: UIColor.red], range: NSMakeRange(8, 7))
2,最上面,划条线
let strokePath = CGMutablePath()
strokePath.addRect(CGRect(x: 1, y: 1, width: UIScreen.main.bounds.width-2, height: 1))
ctx.addPath(strokePath)
ctx.setStrokeColor(UIColor.purple.cgColor)
ctx.strokePath()
CoreText 的坐标系,原点在左下,
UIKit 的坐标系,原点在左上
3,来一个坐标系,翻转
let xHigh = bounds.size.height
ctx.textMatrix = CGAffineTransform.identity
ctx.translateBy(x: 0, y: xHigh)
ctx.scaleBy(x: 1.0, y: -1.0)
4,显示文字
流程是,
拿富文本创建 CTFrame,
拿 CTFrame ,获取里面的 CTLine 集合
把每一行 CTLine,绘制出来
通过 ctx.textPosition,设置每一行的绘制原点
每一行的高度是,lineAscent + lineDescent + lineLeading
先绘制一行,
原点的 y 值 - (lineAscent + lineDescent),
再绘制第二行,就忽略了 lineLeading ( 行间距 )
let path = CGMutablePath()
path.addRect(bounds)
let ctFrameSetter = CTFramesetterCreateWithAttributedString(attributed)
let ctFrame = CTFramesetterCreateFrame(ctFrameSetter, CFRangeMake(0, attributed.length), path, nil)
let lines = CTFrameGetLines(ctFrame) as NSArray
var originsArray = [CGPoint](repeating: CGPoint.zero, count: lines.count)
CTFrameGetLineOrigins(ctFrame, CFRangeMake(0, 0), &originsArray)
var frameY:CGFloat = 0
for (i,line) in lines.enumerated() {
var lineAscent:CGFloat = 0
var lineDescent:CGFloat

本文介绍了如何使用Core Text自定义每个字的位置,从基础的富文本绘制,到创建CTFrame和CTLine,再到实现一行中多个文本框的布局,详细讲解了坐标转换和行间距的计算,提供了github仓库链接供读者参考。
最低0.47元/天 解锁文章
265

被折叠的 条评论
为什么被折叠?



