Initial commit
This commit is contained in:
+54
@@ -0,0 +1,54 @@
|
||||
//
|
||||
// UMComMutiStyleTextView.h
|
||||
// UMCommunity
|
||||
//
|
||||
// Created by umeng on 15-3-5.
|
||||
// Copyright (c) 2015年 Umeng. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "UMComMutiText.h"
|
||||
|
||||
|
||||
|
||||
@class UMComMutiTextRunDelegate,UMComMutiTextRun,UMComMutiStyleTextView;
|
||||
|
||||
@class UMComMutiText;
|
||||
@interface UMComMutiStyleTextView : UIView
|
||||
|
||||
@property (nonatomic, strong) NSMutableArray *checkWords;
|
||||
|
||||
@property (nonatomic, copy) void (^clickOnlinkText)(UMComMutiStyleTextView *mutiStyleTextView,UMComMutiTextRun *run);
|
||||
|
||||
@property (nonatomic,copy) NSString *text; // default is nil
|
||||
@property (nonatomic,copy) NSMutableAttributedString *attributedText;
|
||||
@property (nonatomic,strong) UIFont *font; // default is nil (system font 17 plain)
|
||||
@property (nonatomic,strong) UIColor *textColor; // default is nil (text draws black)
|
||||
@property (nonatomic,assign) CGFloat lineSpace;
|
||||
@property (nonatomic,assign) CGPoint pointOffset;
|
||||
|
||||
@property (nonatomic) id framesetterRef;
|
||||
|
||||
|
||||
@property (nonatomic,strong) NSArray *runs;
|
||||
@property (nonatomic,strong) NSMutableDictionary *runRectDictionary;
|
||||
@property (nonatomic,strong) UMComMutiTextRun *touchRun;
|
||||
|
||||
- (void)setMutiStyleTextViewWithMutiText:(UMComMutiText *)mutiText;
|
||||
|
||||
|
||||
//+ (UMComMutiStyleTextView *)rectDictionaryWithSize:(CGSize)size
|
||||
// font:(UIFont *)font
|
||||
// attString:(NSString *)string
|
||||
// lineSpace:(CGFloat )lineSpace
|
||||
// runType:(UMComMutiTextRunTypeList)runType
|
||||
// checkWords:(NSMutableArray *)checkWords;
|
||||
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+393
@@ -0,0 +1,393 @@
|
||||
//
|
||||
// UMComMutiStyleTextView.m
|
||||
// UMCommunity
|
||||
//
|
||||
// Created by umeng on 15-3-5.
|
||||
// Copyright (c) 2015年 Umeng. All rights reserved.
|
||||
//
|
||||
|
||||
#import "UMComMutiStyleTextView.h"
|
||||
#import "UMComResouceDefines.h"
|
||||
#import <UMComFoundation/UMComKit+Color.h>
|
||||
|
||||
|
||||
@interface UMComMutiStyleTextView ()
|
||||
|
||||
|
||||
@end
|
||||
|
||||
@implementation UMComMutiStyleTextView
|
||||
|
||||
- (id)init
|
||||
{
|
||||
self = [self initWithFrame:CGRectZero];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
if (_framesetterRef) {
|
||||
CFRelease((__bridge_retained CTFramesetterRef)(_framesetterRef));
|
||||
_framesetterRef = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (id)initWithFrame:(CGRect)frame
|
||||
{
|
||||
self = [super initWithFrame:frame];
|
||||
if (self) {
|
||||
[self createDefault];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setMutiStyleTextViewWithMutiText:(UMComMutiText *)mutiText
|
||||
{
|
||||
self.attributedText = mutiText.attributedText;
|
||||
self.framesetterRef = mutiText.framesetterRef;
|
||||
self.runs = mutiText.runs;
|
||||
self.font = mutiText.font;
|
||||
self.lineSpace = mutiText.lineSpace;
|
||||
self.textColor = mutiText.textColor;
|
||||
[self setText:mutiText.text];
|
||||
}
|
||||
|
||||
#pragma mark - CreateDefault
|
||||
|
||||
- (void)createDefault
|
||||
{
|
||||
//public
|
||||
_text = nil;
|
||||
_font = [UIFont systemFontOfSize:13.0f];
|
||||
_textColor = [UIColor blackColor];
|
||||
_lineSpace = 2.0f;
|
||||
// self.heightOffset = 0.0f;
|
||||
_attributedText = nil;
|
||||
_pointOffset = CGPointZero;
|
||||
//private
|
||||
_runs = [NSMutableArray array];
|
||||
_runRectDictionary = [NSMutableDictionary dictionary];
|
||||
_touchRun = nil;
|
||||
_checkWords = [NSMutableArray arrayWithCapacity:1];
|
||||
_framesetterRef = NULL;
|
||||
|
||||
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tapInCerrentView:)];
|
||||
[self addGestureRecognizer:tap];
|
||||
}
|
||||
|
||||
|
||||
|
||||
#pragma mark - Set
|
||||
- (void)setText:(NSString *)text
|
||||
{
|
||||
[self setNeedsDisplay];
|
||||
|
||||
_text = text;
|
||||
}
|
||||
|
||||
|
||||
- (void)awakeFromNib
|
||||
{
|
||||
[self createDefault];
|
||||
|
||||
}
|
||||
|
||||
#pragma mark - Draw Rect
|
||||
|
||||
- (void)drawRect:(CGRect)rect
|
||||
{
|
||||
//绘图上下文
|
||||
CGContextRef contextRef = UIGraphicsGetCurrentContext();
|
||||
if (self.attributedText == nil || self.attributedText.length == 0 ){
|
||||
return;
|
||||
}
|
||||
|
||||
CGRect viewRect = CGRectMake(self.pointOffset.x, -self.pointOffset.y, rect.size.width, rect.size.height);//
|
||||
//修正坐标系
|
||||
CGAffineTransform affineTransform = CGAffineTransformIdentity;
|
||||
affineTransform = CGAffineTransformMakeTranslation(0.0, viewRect.size.height);
|
||||
affineTransform = CGAffineTransformScale(affineTransform, 1.0, -1.0);
|
||||
CGContextConcatCTM(contextRef, affineTransform);
|
||||
|
||||
//创建一个用来描画文字的路径,其区域为viewRect CGPath
|
||||
CGMutablePathRef pathRef = CGPathCreateMutable();
|
||||
CGPathAddRect(pathRef, NULL, viewRect);
|
||||
|
||||
CTFramesetterRef frameSetter = CFRetain((__bridge CTFramesetterRef)(self.framesetterRef));
|
||||
CTFrameRef frameRef = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, 0), pathRef, nil);
|
||||
//通过context在frame中描画文字内容
|
||||
CTFrameDraw(frameRef, contextRef);
|
||||
[self.runRectDictionary removeAllObjects];
|
||||
[self setRunsKeysToRunRectWithFrameRef:frameRef];
|
||||
CGPathRelease(pathRef);
|
||||
CFRelease(frameRef);
|
||||
CFRelease(frameSetter);
|
||||
}
|
||||
|
||||
- (void)setRunsKeysToRunRectWithFrameRef:(CTFrameRef)frameRef
|
||||
{
|
||||
CFArrayRef lines = CTFrameGetLines(frameRef);
|
||||
CGPoint lineOrigins[CFArrayGetCount(lines)];
|
||||
CTFrameGetLineOrigins(frameRef, CFRangeMake(0, 0), lineOrigins);
|
||||
|
||||
for (int i = 0; i < CFArrayGetCount(lines); i++)
|
||||
{
|
||||
CTLineRef lineRef= CFArrayGetValueAtIndex(lines, i);
|
||||
CGFloat lineAscent;
|
||||
CGFloat lineDescent;
|
||||
CGFloat lineLeading;
|
||||
CGPoint lineOrigin = CGPointMake(lineOrigins[i].x, lineOrigins[i].y);//
|
||||
CTLineGetTypographicBounds(lineRef, &lineAscent, &lineDescent, &lineLeading);
|
||||
CFArrayRef runs = CTLineGetGlyphRuns(lineRef);
|
||||
|
||||
for (int j = 0; j < CFArrayGetCount(runs); j++)
|
||||
{
|
||||
CTRunRef runRef = CFArrayGetValueAtIndex(runs, j);
|
||||
CGFloat runAscent;
|
||||
CGFloat runDescent;
|
||||
CGRect runRect;
|
||||
|
||||
runRect.size.width = CTRunGetTypographicBounds(runRef, CFRangeMake(0,0), &runAscent, &runDescent, NULL);
|
||||
runRect = CGRectMake(lineOrigin.x + CTLineGetOffsetForStringIndex(lineRef, CTRunGetStringRange(runRef).location, NULL),
|
||||
lineOrigin.y,
|
||||
runRect.size.width,
|
||||
runAscent + runDescent);
|
||||
|
||||
NSDictionary * attributes = (__bridge NSDictionary *)CTRunGetAttributes(runRef);
|
||||
UMComMutiTextRun *mutiTextRun = [attributes objectForKey:UMComMutiTextRunAttributedName];
|
||||
if (mutiTextRun.drawSelf)
|
||||
{
|
||||
CGFloat runAscent,runDescent;
|
||||
CGFloat runWidth = CTRunGetTypographicBounds(runRef, CFRangeMake(0,0), &runAscent, &runDescent, NULL);
|
||||
CGFloat runHeight = (lineAscent + lineDescent );
|
||||
CGFloat runPointX = runRect.origin.x + lineOrigin.x;
|
||||
CGFloat runPointY = lineOrigin.y;
|
||||
|
||||
CGRect runRectDraw = CGRectMake(runPointX, runPointY, runWidth, runHeight);
|
||||
|
||||
[mutiTextRun drawRunWithRect:runRectDraw];
|
||||
|
||||
[self.runRectDictionary setObject:mutiTextRun forKey:[NSValue valueWithCGRect:runRectDraw]];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mutiTextRun)
|
||||
{
|
||||
[self.runRectDictionary setObject:mutiTextRun forKey:[NSValue valueWithCGRect:runRect]];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (void)tapInCerrentView:(UITapGestureRecognizer *)tap
|
||||
{
|
||||
CGPoint location = [tap locationInView:self];
|
||||
CGPoint runLocation = CGPointMake(location.x-self.pointOffset.x, self.frame.size.height - location.y+self.pointOffset.y+2);
|
||||
|
||||
__weak UMComMutiStyleTextView *weakSelf = self;
|
||||
if (self.clickOnlinkText) {
|
||||
if (self.runRectDictionary.count > 0) {
|
||||
BOOL isInclude = NO;
|
||||
for (NSValue *key in [self.runRectDictionary allKeys]) {
|
||||
id object = [self.runRectDictionary objectForKey:key];
|
||||
CGRect rect = [((NSValue *)key) CGRectValue];
|
||||
if(CGRectContainsPoint(rect, runLocation))
|
||||
{
|
||||
isInclude = YES;
|
||||
weakSelf.touchRun = (UMComMutiTextRun *)object;
|
||||
if ([object isKindOfClass:[UMComMutiTextRunURL class]]) {
|
||||
if (![[weakSelf.touchRun.text lowercaseString] hasPrefix:@"http"]) {
|
||||
weakSelf.touchRun.text = [NSString stringWithFormat:@"http://%@",weakSelf.touchRun.text];
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isInclude == YES) {
|
||||
weakSelf.clickOnlinkText(self,weakSelf.touchRun);
|
||||
}else{
|
||||
weakSelf.clickOnlinkText(self,nil);
|
||||
}
|
||||
}else{
|
||||
weakSelf.clickOnlinkText(self,nil);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//#pragma mark -
|
||||
//
|
||||
//+ (NSMutableAttributedString *)createAttributedStringWithText:(NSString *)text font:(UIFont *)font lineSpace:(CGFloat)lineSpace
|
||||
//{
|
||||
// NSMutableAttributedString *attString = [[NSMutableAttributedString alloc] initWithString:text];
|
||||
// //设置字体
|
||||
// CTFontRef fontRef = CTFontCreateFromUIFont(font);
|
||||
// [attString addAttribute:(NSString*)kCTFontAttributeName value:(__bridge id)fontRef range:NSMakeRange(0,attString.length)];
|
||||
// CFRelease(fontRef);
|
||||
//
|
||||
// //添加换行模式
|
||||
// CTParagraphStyleSetting lineBreakMode;
|
||||
// CTLineBreakMode lineBreak = kCTLineBreakByWordWrapping;
|
||||
// lineBreakMode.spec = kCTParagraphStyleSpecifierLineBreakMode;
|
||||
// lineBreakMode.value = &lineBreak;
|
||||
// lineBreakMode.valueSize = sizeof(lineBreak);
|
||||
//
|
||||
// //行距
|
||||
// CTParagraphStyleSetting lineSpaceStyle;
|
||||
// lineSpaceStyle.spec = kCTParagraphStyleSpecifierLineSpacing;
|
||||
// lineSpaceStyle.valueSize = sizeof(lineSpace);
|
||||
// lineSpaceStyle.value =&lineSpace;
|
||||
//
|
||||
// CTParagraphStyleSetting settings[] = {lineSpaceStyle,lineBreakMode};
|
||||
// CTParagraphStyleRef style = CTParagraphStyleCreate(settings, sizeof(settings)/sizeof(settings[0]));
|
||||
// NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithObject:(__bridge id)style forKey:(id)kCTParagraphStyleAttributeName ];
|
||||
// CFRelease(style);
|
||||
//
|
||||
// [attString addAttributes:attributes range:NSMakeRange(0, [attString length])];
|
||||
////
|
||||
////
|
||||
//// [attString addAttribute:(NSString*)kCTForegroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(0,attString.length)];
|
||||
// return attString;
|
||||
//}
|
||||
|
||||
//+ (NSArray *)createTextRunsWithAttString:(NSMutableAttributedString *)attString
|
||||
// runType:(UMComMutiTextRunTypeList)type
|
||||
// font:(UIFont *)font
|
||||
// checkWords:(NSArray *)checkWords
|
||||
//{
|
||||
// NSMutableArray *array = [[NSMutableArray alloc] init];
|
||||
// UIColor *blueColor = UMComColorWithHexString(FontColorBlue];
|
||||
// if (type == UMComMutiTextRunFeedContentType || type == UMComMutiTextRunCommentType || type == UMComMutiTextRunLikeType || type == UMComMutiTextRunNoneType)
|
||||
// {
|
||||
// NSArray *subRunArray = [UMComMutiTextRunURL runsWithAttributedString:attString font:font textColor:blueColor];
|
||||
// if (subRunArray.count > 0) {
|
||||
// [array addObjectsFromArray:subRunArray];
|
||||
// }
|
||||
// subRunArray = [UMComMutiTextRunTopic runsWithAttributedString:attString font:font textColor:blueColor checkWords:checkWords];
|
||||
// if (subRunArray.count > 0) {
|
||||
// [array addObjectsFromArray:subRunArray];
|
||||
// }
|
||||
// subRunArray = [UMComMutiTextRunClickUser runsWithAttributedString:attString font:font textColor:blueColor checkWords:checkWords];
|
||||
// if (subRunArray.count > 0) {
|
||||
// [array addObjectsFromArray:subRunArray];
|
||||
// }
|
||||
// }
|
||||
// return array;
|
||||
//}
|
||||
|
||||
|
||||
//- (NSArray *)runsWithattributString:(NSMutableAttributedString *)attribuString
|
||||
// Font:(UIFont *)font
|
||||
// lineSpace:(CGFloat )lineSpace
|
||||
// color:(UIColor *)color
|
||||
// checkWords:(NSArray *)checkWords
|
||||
//{
|
||||
// return nil;
|
||||
//}
|
||||
|
||||
//+ (UMComMutiStyleTextView *)rectDictionaryWithSize:(CGSize)size
|
||||
// font:(UIFont *)font
|
||||
// attString:(NSString *)string
|
||||
// lineSpace:(CGFloat )lineSpace
|
||||
// runType:(UMComMutiTextRunTypeList)runType
|
||||
// checkWords:(NSMutableArray *)checkWords
|
||||
//{
|
||||
// UMComMutiStyleTextView * styleTextView = [[UMComMutiStyleTextView alloc] init];
|
||||
// styleTextView.checkWords = checkWords;
|
||||
// styleTextView.font = font;
|
||||
// styleTextView.lineSpace = lineSpace;
|
||||
// [styleTextView rectDictionaryWithSize:size font:font attString:string lineSpace:lineSpace];
|
||||
// return styleTextView;
|
||||
//}
|
||||
|
||||
//- (void)rectDictionaryWithSize:(CGSize)size font:(UIFont *)font attString:(NSString *)string lineSpace:(CGFloat )lineSpace
|
||||
//{
|
||||
// if (!string || string.length == 0) {
|
||||
// return;
|
||||
// }
|
||||
// CGFloat shortestLineWith = 0;
|
||||
// int lineCount = 0;
|
||||
// NSMutableAttributedString *attString = [[self class] createAttributedStringWithText:string font:font lineSpace:lineSpace];
|
||||
// NSDictionary *dic = [attString attributesAtIndex:0 effectiveRange:nil];
|
||||
// CTParagraphStyleRef paragraphStyle = (__bridge CTParagraphStyleRef)[dic objectForKey:(id)kCTParagraphStyleAttributeName];
|
||||
// CGFloat linespace = 0;
|
||||
//
|
||||
// CTParagraphStyleGetValueForSpecifier(paragraphStyle, kCTParagraphStyleSpecifierLineSpacing, sizeof(linespace), &linespace);
|
||||
//
|
||||
// CGFloat height = 0;
|
||||
// CGFloat width = 0;
|
||||
// CFIndex lineIndex = 0;
|
||||
//
|
||||
// CGMutablePathRef pathRef = CGPathCreateMutable();
|
||||
// CGPathAddRect(pathRef, NULL, CGRectMake(0, 0, size.width, size.height));
|
||||
//
|
||||
// NSArray *runs = [[self class] createTextRunsWithAttString:attString runType:0 font:font checkWords:self.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);
|
||||
// CFArrayRef lines = CTFrameGetLines(frameRef);
|
||||
//
|
||||
// lineIndex = CFArrayGetCount(lines);
|
||||
// lineCount = (int)lineIndex;
|
||||
//
|
||||
// CTLineRef lineRef;
|
||||
// if (lineIndex > 1)
|
||||
// {
|
||||
// for (int i = 0; i <lineIndex ; i++)
|
||||
// {
|
||||
// lineRef= CFArrayGetValueAtIndex(lines, i);
|
||||
// if (i == lineIndex - 1) {
|
||||
// CGRect rect = CTLineGetBoundsWithOptions(lineRef,kCTLineBoundsExcludeTypographicShifts);
|
||||
// shortestLineWith = rect.size.width;
|
||||
// }
|
||||
// CGFloat lineAscent;
|
||||
// CGFloat lineDescent;
|
||||
// CGFloat lineLeading;
|
||||
// CTLineGetTypographicBounds(lineRef, &lineAscent, &lineDescent, &lineLeading);
|
||||
//
|
||||
// if (i == lineIndex - 1)
|
||||
// {
|
||||
// height += (lineAscent + lineDescent +linespace);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// height += (lineAscent + lineDescent + linespace);
|
||||
// }
|
||||
// }
|
||||
// width = size.width;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// lineRef= CFArrayGetValueAtIndex(lines, 0);
|
||||
// CGRect rect = CTLineGetBoundsWithOptions(lineRef,kCTLineBoundsExcludeTypographicShifts);
|
||||
// shortestLineWith = rect.size.width;
|
||||
//// self.lineHeight = rect.size.height + linespace;
|
||||
// width = rect.size.width;
|
||||
// CGFloat lineAscent;
|
||||
// CGFloat lineDescent;
|
||||
// CGFloat lineLeading;
|
||||
// CTLineGetTypographicBounds(lineRef, &lineAscent, &lineDescent, &lineLeading);
|
||||
//
|
||||
// height += (lineAscent + lineDescent + lineLeading + linespace);
|
||||
// height = height;
|
||||
// }
|
||||
//
|
||||
//// self.totalHeight = height + lineSpace/2;
|
||||
// self.attributedText = attString;
|
||||
// CGPathRelease(pathRef);
|
||||
// CFRelease(setterRef);
|
||||
// CFRelease(frameRef);
|
||||
//}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
//
|
||||
// UMComMutiText.h
|
||||
// UMCommunity
|
||||
//
|
||||
// Created by umeng on 16/5/4.
|
||||
// Copyright © 2016年 Umeng. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "UMComMutiTextRun.h"
|
||||
|
||||
@interface UMComMutiText : NSObject
|
||||
|
||||
@property (nonatomic,copy) NSString *text; // default is nil
|
||||
@property (nonatomic,strong) UIFont *font; // default is nil (system font 17 plain)
|
||||
@property (nonatomic,strong) UIColor *textColor; // default is nil (text draws black)
|
||||
@property (nonatomic,strong) UIColor *textHighLightColor;
|
||||
|
||||
@property (nonatomic,assign) CGFloat lineSpace;
|
||||
@property (nonatomic,assign) NSInteger lineNumbers;
|
||||
@property (nonatomic,assign) CGSize textSize;
|
||||
@property (nonatomic,assign) CGPoint pointOffset;
|
||||
@property (nonatomic,assign) NSLineBreakMode lineBreakMode;
|
||||
|
||||
@property (nonatomic,assign) NSInteger index;
|
||||
|
||||
@property (nonatomic,copy) NSMutableAttributedString *attributedText;
|
||||
|
||||
@property (nonatomic) id framesetterRef;
|
||||
|
||||
@property (nonatomic,strong) NSArray<UMComMutiTextRun *> *runs;
|
||||
|
||||
- (instancetype)initWithString:(NSString *)string;
|
||||
|
||||
- (instancetype)initWithAttributedString:(NSMutableAttributedString *)attributedString;
|
||||
- (void)setTextColor:(UIColor *)color forRange:(NSRange)range;
|
||||
|
||||
- (void)setTextFont:(UIFont *)font forRange:(NSRange)range;
|
||||
|
||||
|
||||
+ (UMComMutiText *)mutiTextWithSize:(CGSize)size
|
||||
font:(UIFont *)font
|
||||
string:(NSString *)string
|
||||
lineSpace:(CGFloat)lineSpace
|
||||
checkWords:(NSArray *)checkWords;
|
||||
|
||||
+ (UMComMutiText *)mutiTextWithSize:(CGSize)size
|
||||
font:(UIFont *)font
|
||||
string:(NSString *)string
|
||||
lineSpace:(CGFloat)lineSpace
|
||||
checkWords:(NSArray *)checkWords
|
||||
textColor:(UIColor *)textColor;
|
||||
|
||||
+ (UMComMutiText *)mutiTextWithSize:(CGSize)size
|
||||
font:(UIFont *)font
|
||||
string:(NSString *)string
|
||||
lineSpace:(CGFloat)lineSpace
|
||||
checkWords:(NSArray *)checkWords
|
||||
textColor:(UIColor *)textColor
|
||||
highLightColor:(UIColor *)highLightColor;
|
||||
|
||||
@end
|
||||
+294
@@ -0,0 +1,294 @@
|
||||
//
|
||||
// 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
|
||||
+151
@@ -0,0 +1,151 @@
|
||||
//
|
||||
// UMComMutiTextRun.h
|
||||
// UMCommunity
|
||||
//
|
||||
// Created by umeng on 15/8/19.
|
||||
// Copyright (c) 2015年 Umeng. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <CoreText/CoreText.h>
|
||||
|
||||
typedef NS_OPTIONS(NSUInteger, UMComMutiTextRunTypeList)
|
||||
{
|
||||
UMComMutiTextRunNoneType = 0,
|
||||
UMComMutiTextRunLikeType = 1,
|
||||
UMComMutiTextRunCommentType = 2,
|
||||
UMComMutiTextRunFeedContentType = 3,
|
||||
};
|
||||
|
||||
extern NSString * const UMComMutiTextRunAttributedName;
|
||||
|
||||
|
||||
|
||||
//文字单元CTRun
|
||||
|
||||
@interface UMComMutiTextRun : UIResponder
|
||||
|
||||
/**
|
||||
* 文本单元内容
|
||||
*/
|
||||
@property (nonatomic,copy ) NSString *text;
|
||||
|
||||
/**
|
||||
* 文本单元字体
|
||||
*/
|
||||
@property (nonatomic,strong) UIFont *font;
|
||||
|
||||
/**
|
||||
* 文本单元颜色
|
||||
*/
|
||||
@property (nonatomic,strong) UIColor *textColor;
|
||||
|
||||
/**
|
||||
* 文本单元在字符串中的位置
|
||||
*/
|
||||
@property (nonatomic,assign) NSRange range;
|
||||
|
||||
/**
|
||||
* 是否自己绘制自己
|
||||
*/
|
||||
@property(nonatomic,getter = isDrawSelf) BOOL drawSelf;
|
||||
|
||||
/**
|
||||
* 向字符串中添加相关Run类型属性
|
||||
*/
|
||||
- (void)decorateToAttributedString:(NSMutableAttributedString *)attributedString range:(NSRange)range;
|
||||
|
||||
/**
|
||||
* 绘制Run内容
|
||||
*/
|
||||
- (void)drawRunWithRect:(CGRect)rect;
|
||||
|
||||
/**
|
||||
* 初始化方法
|
||||
*/
|
||||
- (id)initWithText:(NSString *)text
|
||||
font:(UIFont *)font
|
||||
textColor:(UIColor *)color
|
||||
range:(NSRange)range;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface UMComMutiTextRunClickUser : UMComMutiTextRun
|
||||
|
||||
/**
|
||||
* 解析字符串中的“@userName ”格式内容生成Run对象
|
||||
*
|
||||
* @param attributedString 内容
|
||||
*
|
||||
* @param font 字体
|
||||
*
|
||||
* @param color 颜色
|
||||
*
|
||||
* @param checkWords 需要匹配的文字数组的文字
|
||||
*
|
||||
* @return UMComMutiTextRunClickUser对象数组
|
||||
*/
|
||||
+ (NSArray *)runsWithAttributedString:(NSMutableAttributedString *)attributedString
|
||||
font:(UIFont *)font
|
||||
textColor:(UIColor *)color
|
||||
checkWords:(NSArray *)checkWords;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface UMComMutiTextRunTopic : UMComMutiTextRun
|
||||
|
||||
/**
|
||||
* 解析字符串中的“#话题#”格式内容生成Run对象
|
||||
*
|
||||
* @param attributedString 内容
|
||||
*
|
||||
* @param font 字体
|
||||
*
|
||||
* @param color 颜色
|
||||
*
|
||||
* @param checkWords 需要匹配的文字数组的文字
|
||||
*
|
||||
* @return UMComMutiTextRunTopic对象数组
|
||||
*/
|
||||
+ (NSArray *)runsWithAttributedString:(NSMutableAttributedString *)attributedString
|
||||
font:(UIFont *)font
|
||||
textColor:(UIColor *)color
|
||||
checkWords:(NSArray *)checkWords;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@interface UMComMutiTextRunURL : UMComMutiTextRun
|
||||
|
||||
/**
|
||||
* 解析字符串中url内容生成Run对象
|
||||
*
|
||||
* @param attributedString 内容
|
||||
*
|
||||
* @param font 字体
|
||||
*
|
||||
* @param color 颜色
|
||||
*
|
||||
* @return UMComMutiTextRunURL对象数组
|
||||
*/
|
||||
+ (NSArray *)runsWithAttributedString:(NSMutableAttributedString *)attributedString
|
||||
font:(UIFont *)font
|
||||
textColor:(UIColor *)color;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface UMComMutiTextRunDelegate : UMComMutiTextRun
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface UMComMutiTextRunEmoji : UMComMutiTextRunDelegate
|
||||
|
||||
+ (NSArray *)runsForAttributedString:(NSMutableAttributedString *)attributedString;
|
||||
|
||||
@end
|
||||
|
||||
+378
@@ -0,0 +1,378 @@
|
||||
//
|
||||
// UMComMutiTextRun.m
|
||||
// UMCommunity
|
||||
//
|
||||
// Created by umeng on 15/8/19.
|
||||
// Copyright (c) 2015年 Umeng. All rights reserved.
|
||||
//
|
||||
|
||||
#import "UMComMutiTextRun.h"
|
||||
#import <CoreText/CoreText.h>
|
||||
#import "UMComResouceDefines.h"
|
||||
//#import <UMComDataStorage/UMComUser.h>
|
||||
//#import <UMComDataStorage/UMComComment.h>
|
||||
//#import <UMComDataStorage/UMComLike.h>
|
||||
//#import <UMComDataStorage/UMComTopic.h>
|
||||
//#import "UMComSyntaxHighlightTextStorage.h"
|
||||
|
||||
|
||||
NSString * const UMComMutiTextRunAttributedName = @"UMComMutiTextRunAttributedName";
|
||||
|
||||
@implementation UMComMutiTextRun
|
||||
|
||||
/**
|
||||
* 向字符串中添加相关Run类型属性
|
||||
*/
|
||||
- (void)decorateToAttributedString:(NSMutableAttributedString *)attributedString range:(NSRange)range
|
||||
{
|
||||
if (attributedString.length == 0) {
|
||||
return;
|
||||
}
|
||||
[attributedString addAttribute:UMComMutiTextRunAttributedName value:self range:range];
|
||||
[attributedString addAttribute:(NSString *)kCTForegroundColorAttributeName value:self.textColor range:range];
|
||||
[attributedString addAttribute:(NSString *)kCTFontAttributeName value:self.font range:range];
|
||||
// self.font = [attributedString attribute:NSFontAttributeName atIndex:0 longestEffectiveRange:nil inRange:range];
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制Run内容
|
||||
*/
|
||||
- (void)drawRunWithRect:(CGRect)rect
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
- (instancetype)initWithText:(NSString *)text
|
||||
font:(UIFont *)font
|
||||
textColor:(UIColor *)color
|
||||
range:(NSRange)range
|
||||
{
|
||||
self = [self init];
|
||||
if (self) {
|
||||
self.text = text;
|
||||
if ([font isKindOfClass:[UIFont class]]) {
|
||||
self.font = font;
|
||||
}
|
||||
if ([color isKindOfClass:[UIColor class]]) {
|
||||
self.textColor = color;
|
||||
}
|
||||
self.range = range;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.font = [UIFont systemFontOfSize:15];
|
||||
self.textColor = [UIColor blueColor];
|
||||
self.drawSelf = NO;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation UMComMutiTextRunClickUser
|
||||
|
||||
- (void)decorateToAttributedString:(NSMutableAttributedString *)attributedString range:(NSRange)range
|
||||
{
|
||||
[super decorateToAttributedString:attributedString range:range];
|
||||
// [attributedString addAttribute:(NSString *)kCTForegroundColorAttributeName value:self.textColor range:range];
|
||||
}
|
||||
|
||||
|
||||
+ (NSArray *)runsWithAttributedString:(NSMutableAttributedString *)attributedString
|
||||
font:(UIFont *)font
|
||||
textColor:(UIColor *)color
|
||||
checkWords:(NSArray *)checkWords
|
||||
{
|
||||
|
||||
NSString *string = attributedString.string;
|
||||
NSMutableArray *array = [NSMutableArray array];
|
||||
|
||||
for (NSString *userName in checkWords) {
|
||||
NSString *userNameRegulaStr = UserRulerString;
|
||||
NSRegularExpression *regular = [NSRegularExpression regularExpressionWithPattern:userNameRegulaStr options:NSRegularExpressionDotMatchesLineSeparators error:nil];
|
||||
NSInteger matchCount = [regular numberOfMatchesInString:userName options:0 range:NSMakeRange(0, [userName length])];
|
||||
if (matchCount > 0) {
|
||||
NSRegularExpression *userNameRegular = [NSRegularExpression regularExpressionWithPattern:userName options:NSRegularExpressionDotMatchesLineSeparators error:nil];
|
||||
NSArray *matchs = [userNameRegular matchesInString:string
|
||||
options:0
|
||||
range:NSMakeRange(0, [string length])];
|
||||
for (NSTextCheckingResult *match in matchs) {
|
||||
UMComMutiTextRunClickUser *run = [[UMComMutiTextRunClickUser alloc] initWithText:userName font:font textColor:color range:match.range];
|
||||
[run decorateToAttributedString:attributedString range:match.range];
|
||||
[array addObject:run];
|
||||
}
|
||||
}
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@implementation UMComMutiTextRunTopic
|
||||
|
||||
/**
|
||||
* 向字符串中添加相关Run类型属性
|
||||
*/
|
||||
- (void)decorateToAttributedString:(NSMutableAttributedString *)attributedString range:(NSRange)range
|
||||
{
|
||||
if (attributedString.length == 0) {
|
||||
return;
|
||||
}
|
||||
[super decorateToAttributedString:attributedString range:range];
|
||||
}
|
||||
|
||||
|
||||
+ (NSArray *)runsWithAttributedString:(NSMutableAttributedString *)attributedString
|
||||
font:(UIFont *)font
|
||||
textColor:(UIColor *)color
|
||||
checkWords:(NSArray *)checkWords
|
||||
{
|
||||
NSString *string = attributedString.string;
|
||||
NSMutableArray *array = [NSMutableArray array];
|
||||
|
||||
for (NSString *topicName in checkWords) {
|
||||
NSString *topicNameRegulaStr = TopicRulerString;
|
||||
NSRegularExpression *regular = [NSRegularExpression regularExpressionWithPattern:topicNameRegulaStr options:NSRegularExpressionDotMatchesLineSeparators error:nil];
|
||||
NSInteger matchCount = [regular numberOfMatchesInString:topicName options:0 range:NSMakeRange(0, [topicName length])];
|
||||
if (matchCount > 0) {
|
||||
NSRegularExpression *topicNameRegular = [NSRegularExpression regularExpressionWithPattern:topicName options:NSRegularExpressionDotMatchesLineSeparators error:nil];
|
||||
NSArray *matchs = [topicNameRegular matchesInString:string
|
||||
options:0
|
||||
range:NSMakeRange(0, [string length])];
|
||||
for (NSTextCheckingResult *match in matchs) {
|
||||
UMComMutiTextRunTopic *run = [[UMComMutiTextRunTopic alloc] initWithText:topicName font:font textColor:color range:match.range];
|
||||
[run decorateToAttributedString:attributedString range:match.range];
|
||||
[array addObject:run];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@implementation UMComMutiTextRunURL
|
||||
|
||||
/**
|
||||
* 向字符串中添加相关Run类型属性
|
||||
*/
|
||||
- (void)decorateToAttributedString:(NSMutableAttributedString *)attributedString range:(NSRange)range
|
||||
{
|
||||
if (attributedString.length == 0) {
|
||||
return;
|
||||
}
|
||||
[super decorateToAttributedString:attributedString range:range];
|
||||
// [attributedString addAttribute:(NSString *)kCTForegroundColorAttributeName value:self.textColor range:range];
|
||||
}
|
||||
|
||||
|
||||
+ (NSArray *)runsWithAttributedString:(NSMutableAttributedString *)attributedString
|
||||
font:(UIFont *)font
|
||||
textColor:(UIColor *)color
|
||||
{
|
||||
NSString *string = attributedString.string;
|
||||
NSMutableArray *array = [NSMutableArray array];
|
||||
|
||||
NSError *error = nil;
|
||||
NSString *regulaStr = @"((http[s]{0,1}|ftp)://[a-zA-Z0-9\\.\\-]+\\.([a-zA-Z]{2,4})(:\\d+)?(/[a-zA-Z0-9\\,\\.\\-~!@#$%^&*+?:_/=<>]*)?)|(www.[a-zA-Z0-9\\.\\-]+\\.([a-zA-Z]{2,4})(:\\d+)?(/[a-zA-Z0-9\\,\\.\\-~!@#$%^&*+?:_/=<>]*)?)";
|
||||
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:regulaStr
|
||||
options:NSRegularExpressionCaseInsensitive
|
||||
error:&error];
|
||||
if (error == nil)
|
||||
{
|
||||
NSArray *arrayOfAllMatches = [regex matchesInString:string
|
||||
options:0
|
||||
range:NSMakeRange(0, [string length])];
|
||||
|
||||
for (NSTextCheckingResult *match in arrayOfAllMatches)
|
||||
{
|
||||
NSString* substringForMatch = [string substringWithRange:match.range];
|
||||
UMComMutiTextRunURL *run = [[UMComMutiTextRunURL alloc] initWithText:substringForMatch font:font textColor:color range:match.range];
|
||||
[run decorateToAttributedString:attributedString range:match.range];
|
||||
[array addObject:run ];
|
||||
}
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
|
||||
@implementation UMComMutiTextRunDelegate
|
||||
|
||||
/**
|
||||
* 向字符串中添加相关Run类型属性
|
||||
*/
|
||||
- (void)decorateToAttributedString:(NSMutableAttributedString *)attributedString range:(NSRange)range
|
||||
{
|
||||
[super decorateToAttributedString:attributedString range:range];
|
||||
|
||||
CTRunDelegateCallbacks callbacks;
|
||||
callbacks.version = kCTRunDelegateVersion1;
|
||||
callbacks.dealloc = UMComMutiTextRunDelegateDeallocCallback;
|
||||
callbacks.getAscent = UMComMutiTextRunDelegateGetAscentCallback;
|
||||
callbacks.getDescent = UMComMutiTextRunDelegateGetDescentCallback;
|
||||
callbacks.getWidth = UMComMutiTextRunDelegateGetWidthCallback;
|
||||
|
||||
CTRunDelegateRef runDelegate = CTRunDelegateCreate(&callbacks, (__bridge void*)self);
|
||||
[attributedString addAttribute:(NSString *)kCTRunDelegateAttributeName value:(__bridge id)runDelegate range:range];
|
||||
CFRelease(runDelegate);
|
||||
|
||||
[attributedString addAttribute:(NSString *)kCTForegroundColorAttributeName value:(id)[UIColor clearColor].CGColor range:range];
|
||||
}
|
||||
|
||||
#pragma mark - RunCallback
|
||||
|
||||
- (void)mutiTextRunDealloc
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
- (CGFloat)mutiTextRunGetAscent
|
||||
{
|
||||
return self.font.ascender;
|
||||
}
|
||||
|
||||
- (CGFloat)mutiTextRunGetDescent
|
||||
{
|
||||
return self.font.descender;
|
||||
}
|
||||
|
||||
- (CGFloat)mutiTextRunGetWidth
|
||||
{
|
||||
return self.font.ascender - self.font.descender;
|
||||
}
|
||||
|
||||
#pragma mark - RunDelegateCallback
|
||||
|
||||
void UMComMutiTextRunDelegateDeallocCallback(void *refCon)
|
||||
{
|
||||
// UMComMutiTextRunDelegate *run =(__bridge UMComMutiTextRunDelegate *) refCon;
|
||||
//
|
||||
// [run mutiTextRunDealloc];
|
||||
}
|
||||
|
||||
//--上行高度
|
||||
CGFloat UMComMutiTextRunDelegateGetAscentCallback(void *refCon)
|
||||
{
|
||||
UMComMutiTextRunDelegate *run =(__bridge UMComMutiTextRunDelegate *) refCon;
|
||||
|
||||
return [run mutiTextRunGetAscent];
|
||||
}
|
||||
|
||||
//--下行高度
|
||||
CGFloat UMComMutiTextRunDelegateGetDescentCallback(void *refCon)
|
||||
{
|
||||
UMComMutiTextRunDelegate *run =(__bridge UMComMutiTextRunDelegate *) refCon;
|
||||
|
||||
return [run mutiTextRunGetDescent];
|
||||
}
|
||||
|
||||
//-- 宽
|
||||
CGFloat UMComMutiTextRunDelegateGetWidthCallback(void *refCon)
|
||||
{
|
||||
UMComMutiTextRunDelegate *run =(__bridge UMComMutiTextRunDelegate *) refCon;
|
||||
|
||||
return [run mutiTextRunGetWidth];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@implementation UMComMutiTextRunEmoji
|
||||
|
||||
/**
|
||||
* 返回表情数组
|
||||
*/
|
||||
+ (NSArray *) emojiStringArray
|
||||
{
|
||||
return [NSArray arrayWithObjects:@"[smile]",@"[cry]",@"[hei]",nil];
|
||||
}
|
||||
|
||||
+ (NSArray *)runsForAttributedString:(NSMutableAttributedString *)attributedString
|
||||
{
|
||||
NSString *markL = @"[";
|
||||
NSString *markR = @"]";
|
||||
NSString *string = attributedString.string;
|
||||
NSMutableArray *array = [NSMutableArray array];
|
||||
NSMutableArray *stack = [NSMutableArray array];
|
||||
|
||||
for (int i = 0; i < string.length; i++)
|
||||
{
|
||||
NSString *s = [string substringWithRange:NSMakeRange(i, 1)];
|
||||
|
||||
if (([s isEqualToString:markL]) || ((stack.count > 0) && [stack[0] isEqualToString:markL]))
|
||||
{
|
||||
if (([s isEqualToString:markL]) && ((stack.count > 0) && [stack[0] isEqualToString:markL]))
|
||||
{
|
||||
[stack removeAllObjects];
|
||||
}
|
||||
|
||||
[stack addObject:s];
|
||||
|
||||
if ([s isEqualToString:markR] || (i == string.length - 1))
|
||||
{
|
||||
NSMutableString *emojiStr = [[NSMutableString alloc] init];
|
||||
for (NSString *c in stack)
|
||||
{
|
||||
[emojiStr appendString:c];
|
||||
}
|
||||
|
||||
if ([[UMComMutiTextRunEmoji emojiStringArray] containsObject:emojiStr])
|
||||
{
|
||||
NSRange range = NSMakeRange(i + 1 - emojiStr.length, emojiStr.length);
|
||||
|
||||
[attributedString replaceCharactersInRange:range withString:@" "];
|
||||
|
||||
UMComMutiTextRunEmoji *run = [[UMComMutiTextRunEmoji alloc] init];
|
||||
run.range = NSMakeRange(i + 1 - emojiStr.length, 1);
|
||||
run.text = emojiStr;
|
||||
run.drawSelf = YES;
|
||||
[run decorateToAttributedString:attributedString range:run.range];
|
||||
[array addObject:run];
|
||||
}
|
||||
|
||||
[stack removeAllObjects];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制Run内容
|
||||
*/
|
||||
- (void)drawRunWithRect:(CGRect)rect
|
||||
{
|
||||
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||
|
||||
NSString *emojiString = [NSString stringWithFormat:@"%@.png",self.text];
|
||||
|
||||
UIImage *image = UMComImageWithImageName(emojiString);
|
||||
if (image)
|
||||
{
|
||||
CGContextDrawImage(context, rect, image.CGImage);
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user