ifish/Ifish/UMCommunity/UMCommunitySDK/UMCommunityUI/CustomView/MutiStyleTextView/UMComMutiText.m

295 lines
10 KiB
Objective-C

//
// UMComMutiText.m
// UMCommunity
//
// Created by umeng on 16/5/4.
// Copyright © 2016年 Umeng. All rights reserved.
//
#import "UMComMutiText.h"
#import "UMComResouceDefines.h"
#import <UMComFoundation/UMComKit+Color.h>
CTFontRef CTFontCreateFromUIFont(UIFont *font)
{
CTFontRef ctFont = CTFontCreateWithName((__bridge CFStringRef)font.fontName,
font.pointSize,
NULL);
return ctFont;
}
@interface UMComMutiText ()
@property (nonatomic, copy) void (^configTextCompletion)();
@property (nonatomic, copy) void (^configTextArrayCompletion)(NSArray *mutiTextArray);
@end
@implementation UMComMutiText
- (instancetype)init
{
self = [super init];
if (self) {
_text = nil;
_font = [UIFont systemFontOfSize:13.0f];
_textColor = [UIColor blackColor];
_lineSpace = 2.0f;
_attributedText = nil;
_pointOffset = CGPointZero;
//private
_runs = [NSMutableArray array];
_framesetterRef = NULL;
}
return self;
}
- (instancetype)initWithString:(NSString *)string
{
NSMutableAttributedString *attString = nil;
if (string && string.length > 0) {
attString = [[NSMutableAttributedString alloc] initWithString:string];
}
_text = string;
self = [self initWithAttributedString:attString];
if (self) {
}
return self;
}
- (instancetype)initWithAttributedString:(NSMutableAttributedString *)attributedString
{
self = [self init];
if (self) {
_attributedText = attributedString;
}
return self;
}
- (void)setFont:(UIFont *)font
{
_font = font;
[self setTextFont:font forRange:NSMakeRange(0,self.attributedText.length)];
}
- (void)setTextColor:(UIColor *)textColor
{
_textColor = textColor;
[self setTextColor:textColor forRange:NSMakeRange(0,self.attributedText.length)];
}
- (void)setTextFont:(UIFont *)font forRange:(NSRange)range
{
NSMutableAttributedString *attString = self.attributedText;
if ([attString isKindOfClass:[NSMutableAttributedString class]] && attString.length > 0) {
//设置字体
CTFontRef fontRef = CTFontCreateFromUIFont(font);//CTFontCreateWithName((__bridge CFStringRef)font.fontName, font.pointSize, NULL);
[attString addAttribute:(NSString*)kCTFontAttributeName value:(__bridge id)fontRef range:range];
CFRelease(fontRef);
}
}
- (void)setTextColor:(UIColor *)color forRange:(NSRange)range
{
if ([_attributedText isKindOfClass:[NSMutableAttributedString class]] && _attributedText.length > 0 && color) {
//设置颜色
[_attributedText addAttribute:(NSString*)kCTForegroundColorAttributeName value:color range:NSMakeRange(0,_attributedText.length)];
}
}
- (void)setLineSpace:(CGFloat)lineSpace
{
_lineSpace = lineSpace;
}
- (void)setLineBreakMode:(NSLineBreakMode)lineBreakMode
{
_lineBreakMode = lineBreakMode;
[self setLineBreakMode:lineBreakMode forRange:NSMakeRange(0, [_attributedText length])];
}
- (void)setLineBreakMode:(NSLineBreakMode)lineBreakMode forRange:(NSRange)range
{
}
+ (UMComMutiText *)mutiTextWithSize:(CGSize)size
font:(UIFont *)font
string:(NSString *)string
lineSpace:(CGFloat)lineSpace
checkWords:(NSArray *)checkWords
{
UMComMutiText *mutiText = [[UMComMutiText alloc]initWithString:string];
[mutiText setMutiTextWithSize:size font:font string:string lineSpace:lineSpace checkWords:checkWords];
mutiText.text = string;
return mutiText;
}
+ (UMComMutiText *)mutiTextWithSize:(CGSize)size
font:(UIFont *)font
string:(NSString *)string
lineSpace:(CGFloat)lineSpace
checkWords:(NSArray *)checkWords
textColor:(UIColor *)textColor
{
UMComMutiText *mutiText = [[UMComMutiText alloc]initWithString:string];
mutiText.textColor = textColor;
[mutiText setMutiTextWithSize:size font:font string:string lineSpace:lineSpace checkWords:checkWords];
mutiText.text = string;
return mutiText;
}
+ (UMComMutiText *)mutiTextWithSize:(CGSize)size
font:(UIFont *)font
string:(NSString *)string
lineSpace:(CGFloat)lineSpace
checkWords:(NSArray *)checkWords
textColor:(UIColor *)textColor
highLightColor:(UIColor *)highLightColor
{
UMComMutiText *mutiText = [[UMComMutiText alloc]initWithString:string];
mutiText.textHighLightColor = highLightColor;
mutiText.textColor = textColor;
[mutiText setMutiTextWithSize:size font:font string:string lineSpace:lineSpace checkWords:checkWords];
mutiText.text = string;
return mutiText;
}
- (void)setMutiTextWithSize:(CGSize)size
font:(UIFont *)font
string:(NSString *)string
lineSpace:(CGFloat)lineSpace
checkWords:(NSArray *)checkWords
{
self.font = font;
self.lineBreakMode = NSLineBreakByCharWrapping;
self.lineSpace = lineSpace;
[self reloadTextDataforRange:NSMakeRange(0, _attributedText.length)];
[self setHightLightAttributedTextWithSize:size checkWords:checkWords];
}
- (void)reloadTextDataforRange:(NSRange)range
{
if ([_attributedText isKindOfClass:[NSMutableAttributedString class]] && _attributedText.length > 0) {
CTLineBreakMode lineBreak = kCTLineBreakByWordWrapping;
switch (_lineBreakMode) {
case NSLineBreakByCharWrapping:
lineBreak = kCTLineBreakByCharWrapping;
break;
case NSLineBreakByClipping:
lineBreak = kCTLineBreakByClipping;
break;
case NSLineBreakByTruncatingHead:
lineBreak = kCTLineBreakByTruncatingHead;
break;
case NSLineBreakByTruncatingTail:
lineBreak = kCTLineBreakByTruncatingTail;
break;
case NSLineBreakByTruncatingMiddle:
lineBreak = kCTLineBreakByTruncatingMiddle;
break;
default:
lineBreak = kCTLineBreakByWordWrapping;
break;
}
CTParagraphStyleSetting settings[] = {
{kCTParagraphStyleSpecifierLineSpacing,sizeof(_lineSpace),&_lineSpace}, //行间距
{ kCTParagraphStyleSpecifierLineSpacingAdjustment, sizeof(CGFloat), &_lineSpace },//调整行间距
{ kCTParagraphStyleSpecifierMaximumLineSpacing, sizeof(CGFloat), &_lineSpace },//最大行间距
{ kCTParagraphStyleSpecifierMinimumLineSpacing, sizeof(CGFloat), &_lineSpace },//最小行间距
{kCTParagraphStyleSpecifierLineBreakMode,sizeof(lineBreak),&lineBreak},//换行模式
};
CTParagraphStyleRef style = CTParagraphStyleCreate(settings, sizeof(settings)/sizeof(settings[0]));
NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithObject:(__bridge id)style forKey:(id)kCTParagraphStyleAttributeName ];
CFRelease(style);
[_attributedText addAttributes:attributes range:range];
}
}
- (void)setHightLightAttributedTextWithSize:(CGSize)size checkWords:(NSArray *)checkWords
{
NSMutableAttributedString *attString = self.attributedText;
if (!attString || attString.length == 0) {
return;
}
CFIndex lineIndex = 0;
int lineCount = 0;
NSDictionary *dic = [attString attributesAtIndex:0 effectiveRange:nil];
CTParagraphStyleRef paragraphStyle = (__bridge CTParagraphStyleRef)[dic objectForKey:(id)kCTParagraphStyleAttributeName];
CGFloat linespace = 0;
CTParagraphStyleGetValueForSpecifier(paragraphStyle, kCTParagraphStyleSpecifierLineSpacing, sizeof(linespace), &linespace);
CGMutablePathRef pathRef = CGPathCreateMutable();
CGPathAddRect(pathRef, NULL, CGRectMake(0, 0, size.width, size.height));
UIColor *blueColor = UMComColorWithHexString(@"#507DAF");
if (!self.textHighLightColor) {
self.textHighLightColor = blueColor;
}
NSArray *runs = [[self class] createTextRunsWithAttString:attString font:_font highLightColor:self.textHighLightColor checkWords:checkWords];
self.runs = runs;
CFAttributedStringRef attStringRef = (__bridge CFAttributedStringRef)attString;
CTFramesetterRef setterRef = CTFramesetterCreateWithAttributedString(attStringRef);
self.framesetterRef = (__bridge_transfer id)(CFRetain(setterRef));
CTFrameRef frameRef = CTFramesetterCreateFrame(setterRef, CFRangeMake(0, 0), pathRef, nil);
CGSize textSize = CTFramesetterSuggestFrameSizeWithConstraints(setterRef, CFRangeMake(0, (CFIndex)[attString length]), NULL, size, NULL);
CFArrayRef lines = CTFrameGetLines(frameRef);
lineIndex = CFArrayGetCount(lines);
lineCount = (int)lineIndex;
self.lineNumbers = lineCount;
CTLineRef lineRef;
if (lineCount > 0) {
lineRef= CFArrayGetValueAtIndex(lines, lineCount-1);
CGRect rect = CTLineGetBoundsWithOptions(lineRef,kCTLineBoundsExcludeTypographicShifts);
if (lineCount == 1) {
textSize.width = rect.size.width+2;//宽度加两个像素以纠偏
}else{
textSize.width = size.width;
}
textSize.height += linespace;//高度加一行高度以纠偏
}
_textSize = textSize;
_attributedText = attString;
CGPathRelease(pathRef);
CFRelease(setterRef);
CFRelease(frameRef);
}
+ (NSArray *)createTextRunsWithAttString:(NSMutableAttributedString *)attString
font:(UIFont *)font
highLightColor:(UIColor *)color
checkWords:(NSArray *)checkWords
{
NSMutableArray *array = [[NSMutableArray alloc] init];
NSArray *subRunArray = [UMComMutiTextRunURL runsWithAttributedString:attString font:font textColor:color];
if (subRunArray.count > 0) {
[array addObjectsFromArray:subRunArray];
}
subRunArray = [UMComMutiTextRunTopic runsWithAttributedString:attString font:font textColor:color checkWords:checkWords];
if (subRunArray.count > 0) {
[array addObjectsFromArray:subRunArray];
}
subRunArray = [UMComMutiTextRunClickUser runsWithAttributedString:attString font:font textColor:color checkWords:checkWords];
if (subRunArray.count > 0) {
[array addObjectsFromArray:subRunArray];
}
return array;
}
@end