iOS CoreText 绘制文本


- (void)drawRect:(CGRect)rect{
    [super drawRect:rect];
    //获取上下文
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    //坐标系x转换 UIKit -> CoreText
    CGContextSetTextMatrix(context, CGAffineTransformIdentity);
    CGContextTranslateCTM(context, 0, self.bounds.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);
    
    //绘制路径
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathAddEllipseInRect(path, NULL, self.bounds);
    
    //显示的字符串
    NSAttributedString *attString = [[NSAttributedString alloc]initWithString:@"this is a text"];
    //创建CTFrameRef实例
    CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attString);
    CTFrameRef frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, attString.length), path, NULL);
    
    //将CTFrame对象画到上下文中
    CTFrameDraw(frame, context);
    
    //释放对象
    CFRelease(frame);
    CFRelease(path);
    CFRelease(frameSetter);
}

swift

class CoreTextView: UIView {
    override func draw(_ rect: CGRect) {
        super.draw(rect)
        
        
        guard let context = UIGraphicsGetCurrentContext() else { return }
        context.translateBy(x: 0, y: kScreenHeight)
        context.scaleBy(x: 1, y: -1)
        context.textMatrix = .identity
        
        let string = "hello world hello world hello world hello world"
        
        // 属性字符串 1 直接设置属性的方式
//        guard let attributeString = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0) else { return }
//        CFAttributedStringReplaceString(attributeString, CFRangeMake(0, 0), string)
//        CFAttributedStringSetAttribute(attributeString, CFRangeMake(0, CFStringGetLength(string)), kCTFontAttributeName, CTFontCreateWithName(kCTFontFamilyNameKey, 20, nil))
        
        
        // 属性字符串 2 直接创建字典的方式
//        let dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, nil, nil)
//        let colorKey = Unmanaged.passRetained(kCTForegroundColorAttributeName).toOpaque()
//        let colorValue = Unmanaged.passRetained(UIColor.red.cgColor).toOpaque()
//        CFDictionaryAddValue(dict, colorKey, colorValue)
//
        
        
        //  段落样式
        var lineSpacing: CGFloat = 5
        var settings: [CTParagraphStyleSetting] = [
            CTParagraphStyleSetting(spec: .lineSpacingAdjustment, valueSize: MemoryLayout.size, value: &lineSpacing)
        ]
        let style = CTParagraphStyleCreate(&settings, settings.count)
        
        let dict: [CFString: Any] = [
            kCTParagraphStyleAttributeName: style,
            kCTForegroundColorAttributeName: UIColor.red
        ]
        let aString = NSAttributedString(string: string, attributes: dict as [NSAttributedString.Key : Any])
        guard let attributeString = CFAttributedStringCreateCopy(kCFAllocatorDefault, aString) else { return }
        
        
        // 整段
        let frameSetter = CTFramesetterCreateWithAttributedString(attributeString)
        let suggestHeight = CTFramesetterSuggestFrameSizeWithConstraints(frameSetter, CFRange(location: 0, length: 0), nil, CGSize(width: 100, height: CGFloat.greatestFiniteMagnitude), nil).height
        
        let path = CGMutablePath()
        path.addRect(CGRect(x: 100, y: 100, width: 100, height: suggestHeight))
        
        let frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, 0), path, nil)
        
        CTFrameDraw(frame, context)
        
        // 单行
//        let line = CTLineCreateWithAttributedString(attributeString)
//        context.textPosition = CGPoint(x: 100, y: 100)
//        CTLineDraw(line, context)
        
        
        //  手动换行
//        var start: CFIndex = 0
//        let maxLength: CFIndex = CFStringGetLength(string)
//        let typesetter = CTTypesetterCreateWithAttributedString(attributeString)
//
//        func drawLine(_ y: CGFloat) {
//            let count = CTTypesetterSuggestLineBreak(typesetter, start, 100)
//            let line = CTTypesetterCreateLine(typesetter, CFRangeMake(start, count))
//            context.textPosition = CGPoint(x: 100, y: y)
//            CTLineDraw(line, context)
//            start += count
//            if start < maxLength {
//                drawLine(y + 30)
//            }
//        }
//        drawLine(100)
        


    }
}

参考:https://www.jianshu.com/p/e0277ac633bc
https://www.jianshu.com/p/6a75446fa9fe
https://www.jianshu.com/p/6db3289fb05d
https://www.jianshu.com/p/e52a38e60e7c

你可能感兴趣的:(iOS CoreText 绘制文本)