CoreText排版

目錄:ui

#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

相關文章
相關標籤/搜索