Core Text 实践:自定义每个字的位置

本文介绍了如何使用Core Text自定义每个字的位置,从基础的富文本绘制,到创建CTFrame和CTLine,再到实现一行中多个文本框的布局,详细讲解了坐标转换和行间距的计算,提供了github仓库链接供读者参考。
摘要由CSDN通过智能技术生成

第一步: 基础

实现下面的效果,注意到每一行的间距为 0

截屏2021-03-22 下午3.06.41.png

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 lineDesc
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值