CoreText是专门用来处理文字和字体的底层技术。直接和2D 图形渲染引擎打交道。效率非常高。 先看实战效果https://github.com/FSilver/FWDrawView
第一步:配置Config
@interface FWDrawConfig : NSObject
@property(nonatomic,strong)NSString *text;
@property(nonatomic,assign)CGFloat width;
@property(nonatomic,assign)UIFont *font;
@property(nonatomic,strong)UIColor *textColor;
@property(nonatomic,strong)UIColor *linkColor;
@property(nonatomic,assign)int underLineOfLink;
@property(nonatomic,assign)NSInteger numberOfLines;
@property(nonatomic,assign)UIEdgeInsets edgInsets;
@end
拿到文本后,先设置文本最大的显示宽度,文本的字体,颜色,文字最大显示行数,文字在控件中上下左右边距。 链接字体的颜色,下划线。
第二步:解析parse
@interface FWDrawParser : NSObject
@property(nonatomic,strong)FWDrawInfo *data;
@property(nonatomic,strong)NSMutableAttributedString *resultAttributeString;
@property(nonatomic,strong)NSDictionary *textAttributeDict;
-(id)initWithConfig:(FWDrawConfig*)config;
-(void)parseEmoji;
-(void)parseUrl;
-(void)parsePhone;
-(void)addLinkWithValue:(id)value range:(NSRange)range;
@end
利用config生成富文本字典,以及富文本呢
-(void)configTextAttributeDictionay
{
//用一个普通的汉子排版的高度,设置为最低高度,保证中文,英文,表情,间距相等,视觉上舒服
//float minLineHight = config.font.lineHeight - config.font.descender;
float minLineHight = _config.font.lineHeight;
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
[paragraphStyle setLineSpacing:0];
[paragraphStyle setMinimumLineHeight:minLineHight];
paragraphStyle.lineHeightMultiple = 0;
NSDictionary *ats = @{
NSFontAttributeName : _config.font,
NSForegroundColorAttributeName:_config.textColor,
NSParagraphStyleAttributeName : paragraphStyle,
};
_textAttributeDict = ats;
}
-(void)configResultAttributeString
{
_resultAttributeString = [[NSMutableAttributedString alloc]init];
NSAttributedString *attributeString = [[NSAttributedString alloc]initWithString:_config.text attributes:_textAttributeDict];
[_resultAttributeString appendAttributedString:attributeString];
}
第三步:数据data
@interface FWDrawInfo : NSObject
@property(nonatomic,assign)CTFrameRef ctFrame;
@property(nonatomic,assign)CGFloat originHeight; //全部显示完全的高度
@property(nonatomic,assign)CGFloat width; //实际宽度
@property(nonatomic,assign)CGFloat height; //实际高度
@property(nonatomic,assign)NSInteger lines; //文本总行数
@property(nonatomic,assign)NSInteger numberOfLines; //限制行数
@property(nonatomic,assign)UIEdgeInsets edgInsets;
@property(nonatomic,strong)NSDictionary *textAttributeDict;
@property(nonatomic,strong)NSAttributedString *attributedString;
@property(nonatomic,strong)NSArray *emojiArray; //赋值的时候,计算区域
@property(nonatomic,strong)NSArray *linkArray; //赋值的时候,计算区域
@end
第四步:绘制data
@class FWDrawView;
@protocol FWDrawViewDelegate <NSObject>
@optional
-(void)didClickFWDraw:(FWDrawView*)draw; //单击
-(void)didLongPressFWDraw:(FWDrawView*)draw;//双击
-(void)didClickFWDraw:(FWDrawView *)draw byLink:(FWDrawLinkInfo*)link; //点击链接
@end
@interface FWDrawView : UIView
@property(nonatomic,weak)id<FWDrawViewDelegate>delegate;
@property(nonatomic,strong)FWDrawInfo *data;
@property(nonatomic,strong)UIColor *linkBgColor;//选中链接后,链接背景色
@property(nonatomic,strong)UIColor *tapColor; //点击View,高亮色
@property(nonatomic,assign)BOOL allowTapGesture; //是否允许单机
@property(nonatomic,assign)BOOL allowLongPressGesture; //是否允许长按
@property(nonatomic,strong)UIColor *longPressColor; //长按View后,view的背景色
@end
绘制方法
-(void)drawRect:(CGRect)rect
{
[super drawRect:rect];
if(self.data == nil){
return;
}
CGContextRef context = UIGraphicsGetCurrentContext();
//坐标系coreText --》 UIkit坐标系
CGContextSetTextMatrix(context, CGAffineTransformIdentity);
CGContextTranslateCTM(context, 0, self.bounds.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
_lastLineOriginY = -1;
_lastLineRightX = -1;
if(_data.numberOfLines == 0 || _data.numberOfLines >= _data.lines){
CTFrameDraw(self.data.ctFrame, context);
}else{
[self drawLineByContext:context];
}
//作用是,画表情
for (FWDrawEmojiInfo * emoji in self.data.emojiArray) {
//转为UI坐标系,表情位置大于有效区域,就break
float y = _data.height - emoji.drawRect.origin.y - emoji.drawRect.size.height;
if(y + emoji.drawRect.size.height > _data.height - _data.edgInsets.bottom){
break;
}
BOOL drawImage = NO;
if(_lastLineOriginY == -1 && _lastLineRightX == -1){
//全部显示
drawImage = YES;
}else{
//限制行数
if(y < _lastLineOriginY){
//不是最后一行
drawImage = YES;
}else if(emoji.drawRect.origin.x + emoji.drawRect.size.width < _lastLineRightX){
//是最后一行
drawImage = YES;
}
}
if(drawImage){
UIImage *image = [UIImage imageNamed:emoji.imageName];
if(image){
CGContextDrawImage(context, emoji.drawRect, image.CGImage);
}
}
}
//作用是,选中链接后,链接高亮显示
for (FWDrawLinkInfo *url in self.data.linkArray) {
for (NSValue *value in url.drawRectArray) {
//转为UI坐标系
CGRect urlRect = [value CGRectValue];
CGFloat y = _data.height - urlRect.origin.y - urlRect.size.height;
if( y + urlRect.size.height > _data.height - _data.edgInsets.bottom){
break;
}
if(url.isSelected){
CGRect urlRect = [value CGRectValue];
CGContextSetFillColorWithColor(context,self.linkBgColor.CGColor);
CGContextFillRect(context , urlRect);
}
}
}
}
完整代码github地址 https://github.com/FSilver/FWDrawView
网友评论