CoreText排版

目录:

231044_JQCf_2319073.png

#import <Foundation/Foundation.h>

//用于配置绘制的参数,例如文字颜色,大小,行间距
@interface CTFrameParserConfig : NSObject
@property (nonatomic,assign)CGFloat width;
@property (nonatomic,assign)CGFloat fontSize;
@property (nonatomic,assign)CGFloat lineSpace;
@property (nonatomic,strong)UIColor *textColor;
@end


#import "CTFrameParserConfig.h"

@implementation CTFrameParserConfig
-(id)init{
    self = [super init];
    if (self){
        _width = 200.0f;
        _fontSize = 16.0f;
        _lineSpace = 0.0f;
        _textColor = RGB(150, 100, 100);
    
    }
    return self;
}
@end
#import <Foundation/Foundation.h>
#import "CTFrameParserConfig.h"
#import "CoreTextData.h"
//用于最后绘制界面需要的CTFrameRef实例
@interface CTFrameParser : NSObject
+(CoreTextData *)parseContext:(NSString *)context config:(CTFrameParserConfig *)config;
+(NSDictionary *)attributesWithConfig:(CTFrameParserConfig *)config;
@end

#import "CTFrameParser.h"

@implementation CTFrameParser
+(NSDictionary *)attributesWithConfig:(CTFrameParserConfig *)config{
    CGFloat fontSize = config.fontSize;
    CTFontRef fontRef = CTFontCreateWithName((CFStringRef)@"ArialMT", fontSize, NULL);
    CGFloat lineSpacing = config.lineSpace;
    const CFIndex kNumberOfSettings = 3;
    CTParagraphStyleSetting theSettings[kNumberOfSettings] = {{kCTParagraphStyleSpecifierLineSpacingAdjustment,sizeof(CGFloat),&lineSpacing},
                                                            {kCTParagraphStyleSpecifierMaximumLineSpacing,sizeof(CGFloat),&lineSpacing},
                                                            {kCTParagraphStyleSpecifierMinimumLineSpacing,sizeof(CGFloat),&lineSpacing}};
    
    CTParagraphStyleRef theParagrapRef = CTParagraphStyleCreate(theSettings, kNumberOfSettings);
    UIColor *textColor = config.textColor;
    
    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    dict[(id)kCTForegroundColorAttributeName] = (id)textColor.CGColor;
    dict[(id)kCTFontAttributeName] = (__bridge id)fontRef;
    dict[(id)kCTParagraphStyleAttributeName] = (__bridge id)theParagrapRef;
    
    CFRelease(theParagrapRef);
    CFRelease(fontRef);
    return dict;
    

}
+(CoreTextData *)parseContext:(NSString *)context config:(CTFrameParserConfig *)config{
    NSDictionary *attributes = [self attributesWithConfig:config];
    NSAttributedString *contextString = [[NSAttributedString alloc]initWithString:context attributes:attributes];
    
    
    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)contextString);
    
    //获得要绘制区域的高度
    CGSize restrictSize = CGSizeMake(config.width, CGFLOAT_MAX);
    CGSize coreTextSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetter, CFRangeMake(0, 0), nil, restrictSize, nil);
    CGFloat textHeight = coreTextSize.height;
    
    CTFrameRef frame = [self createFrameWithFramesetter:framesetter config:config height:textHeight];
    
    //将生成好的CTFrameRef实例和计算好的的绘制高度保存到CoreTectData实例中,最后返回CoreTectData实例
    CoreTextData *data = [[CoreTextData alloc]init];
    data.ctFrame =frame;
    data.height = textHeight;
    
    CFRelease(frame);
    CFRelease(framesetter);
    
    return data;
}
+(CTFrameRef)createFrameWithFramesetter:(CTFramesetterRef)framesetter config:(CTFrameParserConfig *)config height:(CGFloat)height{
   //创建绘制的区域
    CGMutablePathRef path = CGPathCreateMutable();
//    CGPathAddRect(path, NULL, CGRectMake(0, 0, config.width, height));
    CGPathAddRect(path, NULL, CGRectMake(0, -250, config.width+100, 200));//相反于UIKit,底层坐标
    CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL);
    CFRelease(path);
    return frame;
}




@end
#import <Foundation/Foundation.h>
//保存CTFrameParser类生成的CTFrameRef,以及CTFrameRef实质绘制需要的高度
@interface CoreTextData : NSObject

@property (nonatomic ,assign)CTFrameRef ctFrame;
@property (nonatomic ,assign)CGFloat height;//实际使用场景汇总,需要先知道索要显示内容的高度之后才可以进行绘制

@end

#import "CoreTextData.h"

@implementation CoreTextData
-(void)setCtFrame:(CTFrameRef)ctFrame{
    if (_ctFrame != ctFrame){
        if (_ctFrame !=nil){
        
            CFRelease(_ctFrame);
        }
        CFRetain(ctFrame);
        _ctFrame = ctFrame;
    }
}
-(void)dealloc{
    if (_ctFrame != nil){
        CFRelease(_ctFrame);
        _ctFrame = nil;
    }

}
@end
#import <Foundation/Foundation.h>
#import "CoreTextData.h"
//持有CoreTextData的实例,负责将CTFrameRef绘制到界面上
@interface CTSubDisplayView : UIView
@property (strong,nonatomic) CoreTextData *data;
@end

#import "CTSubDisplayView.h"

@implementation CTSubDisplayView
-(void)drawRect:(CGRect)rect{
    [super drawRect:rect];
    //得到当前绘制画布的上下文,用于后续将内容绘制在画布上
    CGContextRef context = UIGraphicsGetCurrentContext();
    //将坐标系上线翻转。对于底层的绘制引擎来说,屏幕的左下角是(0,0)坐标。而对于在上层的UIKit来说,左上角是(0,0)坐标。代码注释后效果如图1.
    CGContextSetTextMatrix(context, CGAffineTransformIdentity);
    CGContextTranslateCTM(context, 100, 100);// 设置UIKit x,y
    CGContextScaleCTM(context, 1.0, -1.0);//拉宽,拉高
    
    if (self.data){
        CTFrameDraw(self.data.ctFrame, context);
    }

}
@end
//  PrefixHeader.pch
#ifndef PrefixHeader_pch
#define PrefixHeader_pch

// Include any system framework and library headers here that should be included in all compilation units.
// You will also need to set the Prefix Header build setting of one or more of your targets to reference this file.

/* iOS other 中
 pch文件  将building setting中prefix header 路径设置$(SRCROOT)/$(PROJECT_NAME)/PrefixHeader.pch
 
 */
//NSLog and UIColor 
#import <UIKit/UIKit.h>
#import <CoreText/CoreText.h>
#import "CTFrameParserConfig.h"
#import "UIView+frameAdjust.h"

#ifdef DEBUG
#define debuglog(...) NSLog(__VA_ARGS__)
#define debugMethod() NSLog(@"%s",__func__)
#else
#define debugLog(...)
#define debugMethod()
#endif

#define RGB(A,B,C) [UIColor colorWithRed:A/255.0 green:B/255.0 blue:C/255.0 alpha:1.0]
#endif /* PrefixHeader_pch */
#import <UIKit/UIKit.h>

@interface UIView (frameAdjust)
-(CGFloat)x;
-(void)setX:(CGFloat)x;

-(CGFloat)y;
-(void)setY:(CGFloat)y;

-(CGFloat)height;
-(void)setHeight:(CGFloat)height;

-(CGFloat)width;
-(void)setWidth:(CGFloat)width;
@end

#import "UIView+frameAdjust.h"

@implementation UIView (frameAdjust)
-(CGFloat)x{

    return self.frame.origin.x;
}
-(void)setX:(CGFloat)x{
    self.frame = CGRectMake(x, self.y, self.width, self.height);
}

-(CGFloat)y{
    return self.frame.origin.y;
}
-(void)setY:(CGFloat)y{
    self.frame = CGRectMake(self.x, y, self.width, self.height);
}

-(CGFloat)height{
    return self.frame.size.height;
}
-(void)setHeight:(CGFloat)height{
    self.frame = CGRectMake(self.x, self.y, self.width, height);
}

-(CGFloat)width{
    return self.frame.size.width;
}
-(void)setWidth:(CGFloat)width{
    self.frame = CGRectMake(self.x, self.y, width, self.height);
}
@end
#import <UIKit/UIKit.h>
#import "CTSubDisplayView.h"
#import "CTFrameParserConfig.h"
@interface ViewController : UIViewController

@property (nonatomic ,strong) CTSubDisplayView *ctView;
@end


#import "ViewController.h"
#import "CTFrameParser.h"
#import "CoreTextData.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    CTFrameParserConfig *config = [[CTFrameParserConfig alloc]init];
    config.textColor = [UIColor redColor];
    config.width = self.ctView.width;
    
    //定制排版文件格式
    NSString *content = @"让CTFrameParser 支持接收NSAttributedString作为参数";
    NSDictionary *attr = [CTFrameParser attributesWithConfig:config];
    NSMutableAttributedString *attributesString = [[NSMutableAttributedString alloc]initWithString:content attributes:attr];
    [attributesString addAttribute:NSForegroundColorAttributeName value:[UIColor blueColor] range:NSMakeRange(0, 7)];
    
    
//    CoreTextData *data = [CTFrameParser parseContext:@"按照以上原则,我们将‘CTSubDisplayView’中的部分内容拆分" config:config];
    CoreTextData *data = [CTFrameParser parseContext:content config:config];//颜色未生效
    self.ctView.data = data;
    self.ctView.height = data.height;
    self.ctView.backgroundColor = [UIColor yellowColor];
  
    self.view = self.ctView;
}


-(CTSubDisplayView *)ctView{
    if (!_ctView){
        _ctView = [[CTSubDisplayView alloc]init];
    
    }

    return _ctView;
}
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

231455_4amm_2319073.png

231455_n4tC_2319073.png

231455_Db7b_2319073.png


转载于:https://my.oschina.net/u/2319073/blog/665496

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值