上一篇文章介紹了CJLabel的實(shí)現(xiàn)跳芳,在V2.0.0
版本之前,CJLabel的圖文顯示是基于NSAttributedString來實(shí)現(xiàn)的竹勉,但有若干不足:
- 圖片點(diǎn)擊響應(yīng)只支持emoji表情飞盆,對于NSAttributedString中通過NSTextAttachment添加的圖片,無法響應(yīng)點(diǎn)擊饶米。
- 點(diǎn)擊鏈點(diǎn)的判斷:核心方法是調(diào)用
CTLineGetStringIndexForPosition()
獲取當(dāng)前觸摸點(diǎn)CGPoint在NSString中對應(yīng)的index桨啃,再判斷該index是否屬于點(diǎn)擊鏈點(diǎn)的NSRange。然而當(dāng)文本中包含多個(gè)emoji表情時(shí)檬输,CTLineGetStringIndexForPosition()
的獲取并不準(zhǔn)確照瘾,特別是如果當(dāng)前點(diǎn)擊鏈點(diǎn)處在文本的最后一行時(shí),存在較大的誤差丧慈。 - 無法響應(yīng)長按點(diǎn)擊析命,另外點(diǎn)擊鏈點(diǎn)不能設(shè)置點(diǎn)擊高亮屬性主卫。
針對以上問題,我對CJLabel 進(jìn)行了重構(gòu)優(yōu)化鹃愤,下面就來看看CJLabel 新的實(shí)現(xiàn)簇搅。
開始之前先來看幾張圖(某些圖片來自網(wǎng)絡(luò))
字形與字符
- Bounding Box(邊界框 bbox),這是一個(gè)假想的框子软吐,它盡可能緊密的將字形包括瘩将。
- Baseline(基線),一條假想的線,一行上的字形都以此線作為上下位置的參考凹耙。
- Origin(每一行的原點(diǎn))姿现,Origin是在圖中的Baseline的左側(cè)。
- Ascent(上行高度)從原點(diǎn)到字體中最高(這里的高深都是以基線為參照線的)的字形的頂部的距離肖抱,Ascent是一個(gè)正值备典。
- Descent(下行高度)從原點(diǎn)到字體中最深的字形底部的距離,Descent是一個(gè)負(fù)值意述。
-
Linegap(行距)提佣,Linegap也可以稱作leading(其實(shí)準(zhǔn)確點(diǎn)講應(yīng)該叫做External leading)。
</br>
字符描述屬性.jpg上圖中綠色線條表示基線荤崇,黃色線條表示下行高度拌屏,綠色線條到紅框最頂部的距離為上行高度,而黃色線條到紅框底部的距離為行間距术荤。因此行高的計(jì)算公式是lineHeight = Ascent + |Descent| + Leading
CoreText繪制NSAttributedString
CoreText是iOS/OSX里的文字渲染引擎槐壳,它會把一行里連在一起相同屬性的文字合在一起作為一個(gè)CTRun,每一行是一個(gè)CTLine喜每,多行合在一起組成CTFrame务唐。如上圖,第一行的文字有兩種樣式带兜,第一部分是加粗枫笛,第二部分是斜體,因?yàn)闃邮讲煌苑殖闪藘蓚€(gè)CTRun刚照,CTLine包含了這兩個(gè)CTRun刑巧,CTFrame包含了所有CTLine。
NSAttributeString可以通過CoreText提供的方法生成CTFramesetter无畔,CTFramesetter是用于創(chuàng)建CTFrame的工廠啊楚,給CTFramesetter一個(gè)CGPath,或者簡單理解為給他一個(gè)框框浑彰,它就會通過它持有的CTTypesetter生成CTFrame恭理,CTFrame生成時(shí)里面包含的CTLine和CTRun就全部生成好了,可以直接繪制到畫布上郭变。CTFrame/CTLine/CTRun都提供了渲染接口颜价,但前兩者是封裝涯保,最后實(shí)際都是調(diào)用到CTRun的渲染接口去繪制。
新建UILabel子類周伦,重寫- (void)drawTextInRect:(CGRect)rect
繪制NSAttributeString
- (void)drawTextInRect:(CGRect)rect {
NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc]initWithString:@"這是一段測試數(shù)據(jù)"];
[attributedText addAttribute:NSForegroundColorAttributeName value:[UIColor blueColor] range:NSMakeRange(2, 2)];
[attributedText addAttribute:NSFontAttributeName value:[UIFont boldSystemFontOfSize:15] range:NSMakeRange(2, 2)];
CGContextRef c = UIGraphicsGetCurrentContext();
// 先將當(dāng)前圖形狀態(tài)推入堆棧
CGContextSaveGState(c);
// 設(shè)置字形變換矩陣為CGAffineTransformIdentity夕春,也就是說每一個(gè)字形都不做圖形變換
CGContextSetTextMatrix(c, CGAffineTransformIdentity);
// 坐標(biāo)轉(zhuǎn)換,iOS 坐標(biāo)原點(diǎn)在左上角专挪,Mac OS 坐標(biāo)原點(diǎn)在左下角
CGContextTranslateCTM(c, 0.0f, rect.size.height);
// CTM 坐標(biāo)移翻轉(zhuǎn)
CGContextScaleCTM(c, 1.0f, -1.0f);
//生成 CTFramesetterRef
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attributedText);
CFRange textRange = CFRangeMake(0, (CFIndex)[attributedText length]);
// 獲取path
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, rect);
//生成 CTFrameRef
CTFrameRef frame = CTFramesetterCreateFrame(framesetter, textRange, path, NULL);
//獲取所有行
CFArrayRef lines = CTFrameGetLines(frame);
//原點(diǎn)數(shù)組
CGPoint lineOrigins[CFArrayGetCount(lines)];
//獲取所有CTLineRef的原點(diǎn)
CTFrameGetLineOrigins(frame, CFRangeMake(0, CFArrayGetCount(lines)), lineOrigins);
for (CFIndex lineIndex = 0; lineIndex < CFArrayGetCount(lines); lineIndex++) {
CGPoint lineOrigin = lineOrigins[lineIndex];
CGContextSetTextPosition(c, lineOrigin.x, lineOrigin.y);
CTLineRef line = CFArrayGetValueAtIndex(lines, lineIndex);
//繪制當(dāng)前行
CTLineDraw(line, c);
}
CFRelease(frame);
CGPathRelease(path);
CFRelease(framesetter);
CGContextRestoreGState(c);
}
NSAttributedString圖文混排
NSAttributedString插入圖片可以通過
CTRunDelegateCallbacks
來實(shí)現(xiàn)及志,如上圖所示,藍(lán)色CTRun設(shè)置了CTRunDelegateRef
寨腔,并在需要插入圖片的位置以空白字符串代替困肩。CoreText逐行繪制文字,當(dāng)繪制到藍(lán)色CTRun時(shí)脆侮,會觸發(fā)CTRunDelegateCallbacks
的相關(guān)回調(diào):
void RunDelegateDeallocCallback(void * refCon) {
}
//獲取圖片高度
CGFloat RunDelegateGetAscentCallback(void * refCon) {
return [(NSNumber *)[(__bridge NSDictionary *)refCon objectForKey:kCJImageHeight] floatValue];
}
CGFloat RunDelegateGetDescentCallback(void * refCon) {
return 0;
}
//獲取圖片寬度
CGFloat RunDelegateGetWidthCallback(void * refCon) {
return [(NSNumber *)[(__bridge NSDictionary *)refCon objectForKey:kCJImageWidth] floatValue];
}
在指定位置插入圖片
/**
指定位置插入圖片
@param line 當(dāng)前繪制行
@param c CGContextRef
@param lineOrigins CTLine坐標(biāo)原點(diǎn)
@param lineIndex 第幾行
*/
- (void)drawImageLine:(CTLineRef)line
context:(CGContextRef)c
lineOrigins:(CGPoint[])lineOrigins
lineIndex:(CFIndex)lineIndex
{
CFArrayRef runs = CTLineGetGlyphRuns(line);
for (int j = 0; j < CFArrayGetCount(runs); j++) {
CGFloat runAscent;
CGFloat runDescent;
CGPoint lineOrigin = lineOrigins[lineIndex];
//獲取每個(gè)CTRun
CTRunRef run = CFArrayGetValueAtIndex(runs, j);
NSDictionary* attributes = (NSDictionary*)CTRunGetAttributes(run);
CGRect runRect;
//調(diào)整CTRun的rect
runRect.size.width = CTRunGetTypographicBounds(run, CFRangeMake(0,0), &runAscent, &runDescent, NULL);
runRect = CGRectMake(lineOrigin.x + CTLineGetOffsetForStringIndex(line, CTRunGetStringRange(run).location, NULL), lineOrigin.y - runDescent, runRect.size.width, runAscent + runDescent);
NSDictionary *imgInfoDic = attributes[kCJImageAttributeName];
if (imgInfoDic[kCJImageName]) {
UIImage *image = [UIImage imageNamed:imgInfoDic[kCJImageName]];
if (image) {
CGRect imageDrawRect;
CGFloat imageSizeWidth = ceil(runRect.size.width);
CGFloat imageSizeHeight = ceil(runRect.size.height);
imageDrawRect.size = CGSizeMake(imageSizeWidth, imageSizeHeight);
imageDrawRect.origin.x = runRect.origin.x + lineOrigin.x;
imageDrawRect.origin.y = lineOrigin.y;
CGContextDrawImage(c, imageDrawRect, image.CGImage);
}
}
}
}
CJLabel點(diǎn)擊鏈點(diǎn)的判斷
前面我們了解了CoreText在UILabel上面的圖文混排繪制的過程,而且在繪制過程中細(xì)化到了每一行
CTLine
的CTRun
勇劣,那何不將點(diǎn)擊鏈點(diǎn)對應(yīng)的CTRun
也做上標(biāo)記靖避;在繪制的過程中判斷到當(dāng)前CTRun
是點(diǎn)擊鏈點(diǎn)則將其對應(yīng)的CGRect
保存到NSArray中。
再在- touchesBegan: withEvent:
事件中判斷觸摸點(diǎn)是否在NSArray里的CGRect
里面比默,核心調(diào)用方法CGRectContainsPoint(bounds, point)
幻捏。
這樣就徹底告別了CTLineGetStringIndexForPosition()
的判斷邏輯,而且CGRectContainsPoint
的判斷準(zhǔn)確度更高命咐。
對于如何標(biāo)記點(diǎn)擊鏈點(diǎn)的CTRun
篡九,這就輪到NSMutableAttributedString
上場了,調(diào)用它的實(shí)例方法- (void)addAttribute:(NSString *)name value:(id)value range:(NSRange)range
醋奠,可以在指定位置添加自定義屬性(前面說到的標(biāo)記插入圖片榛臼,也就是這樣做的)。
*** 另外CJLabel新增了以下屬性:***
新增屬性能夠?qū)χ付ㄎ恢玫淖址砑颖尘吧芩尽⒚柽吪嫔啤Ⅻc(diǎn)擊高亮的效果。
/**
背景填充顏色塞祈。值為UIColor金刁。默認(rèn) `nil`。
該屬性優(yōu)先級低于NSBackgroundColorAttributeName议薪,如果設(shè)置NSBackgroundColorAttributeName會覆蓋kCJBackgroundFillColorAttributeName
*/
extern NSString * const kCJBackgroundFillColorAttributeName;
/**
背景邊框線顏色尤蛮。值為UIColor。默認(rèn) `nil`
*/
extern NSString * const kCJBackgroundStrokeColorAttributeName;
/**
背景邊框線寬度斯议。值為NSNumber产捞。默認(rèn) `1.0f`
*/
extern NSString * const kCJBackgroundLineWidthAttributeName;
/**
背景邊框線圓角角度。值為NSNumber哼御。默認(rèn) `5.0f`
*/
extern NSString * const kCJBackgroundLineCornerRadiusAttributeName;
/**
點(diǎn)擊時(shí)候的背景填充顏色轧葛。值為UIColor搂抒。默認(rèn) `nil`。
該屬性優(yōu)先級低于NSBackgroundColorAttributeName尿扯,如果設(shè)置NSBackgroundColorAttributeName會覆蓋kCJActiveBackgroundFillColorAttributeName
*/
extern NSString * const kCJActiveBackgroundFillColorAttributeName;
/**
點(diǎn)擊時(shí)候的背景邊框線顏色求晶。值為UIColor。默認(rèn) `nil`
*/
extern NSString * const kCJActiveBackgroundStrokeColorAttributeName;
CJLabel實(shí)現(xiàn)邏輯
實(shí)現(xiàn)邏輯總結(jié)如下:
- 在NSAttributedString中對點(diǎn)擊鏈點(diǎn)衷笋、插入圖片芳杏、添加圓角背景或者描邊的字符進(jìn)行標(biāo)記;
- 根據(jù)NSAttributedString中的標(biāo)記辟宗,獲取對應(yīng)字符在label中的CGRect爵赵、自定義參數(shù)、圖片名稱等信息泊脐,并保存在NSArray中空幻;
- 逐行繪制CTLine。CoreText先在指定位置填充背景色容客,然后繪制文字秕铛,接著在插入圖片的位置繪制圖片,最后在指定位置添加描邊(CoreText繪制是疊加覆蓋的缩挑,要注意層級關(guān)系)但两;
- 點(diǎn)擊label,在
- touchesBegan:withEvent:
以及UILongPressGestureRecognizer
長按回調(diào)事件中供置,將觸摸點(diǎn)CGPoint與CGRect數(shù)組做遍歷判斷CGRectContainsPoint(bounds, point)
谨湘,找到對應(yīng)字符并響應(yīng)回調(diào)事件。
當(dāng)然實(shí)現(xiàn)細(xì)節(jié)中還包括了不少其他的復(fù)雜邏輯處理芥丧,這里就不一一說明了紧阔,有興趣的可以下載源碼看看。
CJLabel類
CJLabel響應(yīng)點(diǎn)擊以及長按點(diǎn)擊事件续担,回調(diào)事件可選擇CJLabelLinkModelBlock
或CJLabelLinkDelegate
來實(shí)現(xiàn)寓辱。
@protocol CJLabelLinkDelegate <NSObject>
@optional
/**
點(diǎn)擊鏈點(diǎn)回調(diào)
@param label 點(diǎn)擊label
@param linkModel 鏈點(diǎn)model
*/
- (void)CJLable:(CJLabel *)label didClickLink:(CJLabelLinkModel *)linkModel;
/**
長按點(diǎn)擊鏈點(diǎn)回調(diào)
@param label 點(diǎn)擊label
@param linkModel 鏈點(diǎn)model
*/
- (void)CJLable:(CJLabel *)label didLongPressLink:(CJLabelLinkModel *)linkModel;
@end
IB_DESIGNABLE
/**
* CJLabel 繼承自 UILabel,其文本繪制基于NSAttributedString實(shí)現(xiàn)赤拒,同時(shí)增加了圖文混排秫筏、富文本展示以及添加自定義點(diǎn)擊鏈點(diǎn)并設(shè)置點(diǎn)擊鏈點(diǎn)文本屬性的功能。
*
*
* CJLabel 與 UILabel 不同點(diǎn):
*
1. `- init` 不可直接調(diào)用init初始化挎挖,請使用`initWithFrame:` 或 `initWithCoder:`这敬,以便完成相關(guān)初始屬性設(shè)置
2. `attributedText` 與 `text` 均可設(shè)置文本,注意 [self setText:text]中 text類型只能是NSAttributedString或NSString
3. `NSAttributedString`不再通過`NSTextAttachment`顯示圖片(使用`NSTextAttachment`不會起效)蕉朵,請調(diào)用
`- configureAttributedString: addImageName: imageSize: atIndex: attributes:`或者
`- configureLinkAttributedString: addImageName: imageSize: atIndex: linkAttributes: activeLinkAttributes: parameter: clickLinkBlock: longPressBlock:`方法添加圖片
4. 新增`extendsLinkTouchArea`崔涂, 設(shè)置是否加大點(diǎn)擊響應(yīng)范圍,類似于UIWebView的鏈點(diǎn)點(diǎn)擊效果
5. 新增`shadowRadius`始衅, 設(shè)置文本陰影模糊半徑冷蚂,可與 `shadowColor`刮萌、`shadowOffset` 配合設(shè)置羊壹,注意改設(shè)置將對全局文本起效
6. 新增`textInsets` 設(shè)置文本內(nèi)邊距
7. 新增`verticalAlignment` 設(shè)置垂直方向的文本對齊方式
8. 新增`delegate` 點(diǎn)擊鏈點(diǎn)代理
*
*
* CJLabel 已知bug:
*
`numberOfLines`大于0且小于實(shí)際`label.numberOfLines`韩容,同時(shí)`verticalAlignment`不等于`CJContentVerticalAlignmentTop`時(shí)汞舱,文本顯示位置有偏差
*
*/
@interface CJLabel : UILabel
/**
* 指定初始化函數(shù)為 initWithFrame: 或 initWithCoder:
* 直接調(diào)用 init 會忽略相關(guān)屬性的設(shè)置,所以不能直接調(diào)用 init 初始化.
*/
- (instancetype)init NS_UNAVAILABLE;
/**
* 對應(yīng)UILabel的attributedText屬性
*/
@property (readwrite, nonatomic, copy) NSAttributedString *attributedText;
/**
* 對應(yīng)UILabel的text屬性
*/
@property (readwrite, nonatomic, copy) id text;
/**
* 是否加大點(diǎn)擊響應(yīng)范圍隆夯,類似于UIWebView的鏈點(diǎn)點(diǎn)擊效果钳恕,默認(rèn)NO
*/
@property (readwrite, nonatomic, assign) IBInspectable BOOL extendsLinkTouchArea;
/**
* 陰影模糊半徑,值為0表示沒有模糊蹄衷,值越大越模糊忧额,該值不能為負(fù), 默認(rèn)值為0愧口。
* 可與 `shadowColor`睦番、`shadowOffset` 配合設(shè)置
*/
@property (readwrite, nonatomic, assign) CGFloat shadowRadius;
/**
* 繪制文本的內(nèi)邊距,默認(rèn)UIEdgeInsetsZero
*/
@property (readwrite, nonatomic, assign) UIEdgeInsets textInsets;
/**
* 當(dāng)text rect 小于 label frame 時(shí)文本在垂直方向的對齊方式耍属,默認(rèn) CJVerticalAlignmentCenter
*/
@property (readwrite, nonatomic, assign) CJLabelVerticalAlignment verticalAlignment;
/**
點(diǎn)擊鏈點(diǎn)代理對象
*/
@property (readwrite, nonatomic, weak) id<CJLabelLinkDelegate> delegate;
/**
* return 計(jì)算NSAttributedString字符串的size大小
*
* @param attributedString NSAttributedString字符串
* @param size 預(yù)計(jì)大型邢(比如:CGSizeMake(320, CGFLOAT_MAX))
* @param numberOfLines 指定行數(shù)(0表示不限制)
*
* @return 結(jié)果size
*/
+ (CGSize)sizeWithAttributedString:(NSAttributedString *)attributedString
withConstraints:(CGSize)size
limitedToNumberOfLines:(NSUInteger)numberOfLines;
// 在指定位置插入圖片,圖片所在行恬涧,圖文在垂直方向的對齊方式默認(rèn):底部對齊
+ (NSMutableAttributedString *)configureAttributedString:(NSAttributedString *)attrStr
addImageName:(NSString *)imageName
imageSize:(CGSize)size
atIndex:(NSUInteger)loc
attributes:(NSDictionary *)attributes;
// 在指定位置插入可點(diǎn)擊鏈點(diǎn)圖片,圖片所在行碴巾,圖文在垂直方向的對齊方式默認(rèn):底部對齊
+ (NSMutableAttributedString *)configureLinkAttributedString:(NSAttributedString *)attrStr
addImageName:(NSString *)imageName
imageSize:(CGSize)size
atIndex:(NSUInteger)loc
linkAttributes:(NSDictionary *)linkAttributes
activeLinkAttributes:(NSDictionary *)activeLinkAttributes
parameter:(id)parameter
clickLinkBlock:(CJLabelLinkModelBlock)clickLinkBlock
longPressBlock:(CJLabelLinkModelBlock)longPressBlock;
/**
在指定位置插入圖片溯捆,并返回插入圖片后的NSMutableAttributedString(圖片占位符所占的NSRange={loc,1})
注意!O闷啊提揍!插入圖片, 如果設(shè)置 NSParagraphStyleAttributeName 屬性煮仇,例如:
NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init];
paragraph.lineBreakMode = NSLineBreakByCharWrapping;
[attrStr addAttribute:NSParagraphStyleAttributeName value:paragraph range:range];
請保證 paragraph.lineBreakMode = NSLineBreakByCharWrapping劳跃,不然當(dāng)Label的寬度不夠顯示內(nèi)容或圖片時(shí),不會自動換行, 部分圖片將會看不見
默認(rèn) paragraph.lineBreakMode = NSLineBreakByCharWrapping
@param attrStr 需要插入圖片的NSAttributedString
@param imageName 圖片名稱
@param size 圖片大小
@param loc 圖片插入位置
@param verticalAlignment 圖片所在行浙垫,圖片與文字在垂直方向的對齊方式(只針對當(dāng)前行)
@param attributes 圖片文本屬性
@return 插入圖片后的NSMutableAttributedString
*/
+ (NSMutableAttributedString *)configureAttributedString:(NSAttributedString *)attrStr
addImageName:(NSString *)imageName
imageSize:(CGSize)size
atIndex:(NSUInteger)loc
verticalAlignment:(CJLabelVerticalAlignment)verticalAlignment
attributes:(NSDictionary *)attributes;
/**
在指定位置插入圖片刨仑,插入圖片為可點(diǎn)擊的鏈點(diǎn)!<欣选杉武!
返回插入圖片后的NSMutableAttributedString(圖片占位符所占的NSRange={loc,1})
@param attrStr 需要插入圖片的NSAttributedString
@param imageName 圖片名稱
@param size 圖片大小
@param loc 圖片插入位置
@param verticalAlignment 圖片所在行,圖片與文字在垂直方向的對齊方式(只針對當(dāng)前行)
@param linkAttributes 圖片鏈點(diǎn)屬性
@param activeLinkAttributes 點(diǎn)擊狀態(tài)下的圖片鏈點(diǎn)屬性
@param parameter 鏈點(diǎn)自定義參數(shù)
@param clickLinkBlock 鏈點(diǎn)點(diǎn)擊回調(diào)
@param longPressBlock 長按點(diǎn)擊鏈點(diǎn)回調(diào)
@return 插入圖片后的NSMutableAttributedString
*/
+ (NSMutableAttributedString *)configureLinkAttributedString:(NSAttributedString *)attrStr
addImageName:(NSString *)imageName
imageSize:(CGSize)size
atIndex:(NSUInteger)loc
verticalAlignment:(CJLabelVerticalAlignment)verticalAlignment
linkAttributes:(NSDictionary *)linkAttributes
activeLinkAttributes:(NSDictionary *)activeLinkAttributes
parameter:(id)parameter
clickLinkBlock:(CJLabelLinkModelBlock)clickLinkBlock
longPressBlock:(CJLabelLinkModelBlock)longPressBlock;
/**
根據(jù)指定NSRange配置富文本
@param attrStr NSAttributedString源
@param range 指定NSRange
@param attributes 文本屬性
@return 返回新的NSMutableAttributedString
*/
+ (NSMutableAttributedString *)configureAttributedString:(NSAttributedString *)attrStr
atRange:(NSRange)range
attributes:(NSDictionary *)attributes;
/**
根據(jù)指定NSRange配置富文本辙售,指定NSRange文本為可點(diǎn)擊鏈點(diǎn)G岜А!旦部!
@param attrStr NSAttributedString源
@param range 指定NSRange
@param linkAttributes 鏈點(diǎn)文本屬性
@param activeLinkAttributes 點(diǎn)擊狀態(tài)下的鏈點(diǎn)文本屬性
@param parameter 鏈點(diǎn)自定義參數(shù)
@param clickLinkBlock 鏈點(diǎn)點(diǎn)擊回調(diào)
@param longPressBlock 長按點(diǎn)擊鏈點(diǎn)回調(diào)
@return 返回新的NSMutableAttributedString
*/
+ (NSMutableAttributedString *)configureLinkAttributedString:(NSAttributedString *)attrStr
atRange:(NSRange)range
linkAttributes:(NSDictionary *)linkAttributes
activeLinkAttributes:(NSDictionary *)activeLinkAttributes
parameter:(id)parameter
clickLinkBlock:(CJLabelLinkModelBlock)clickLinkBlock
longPressBlock:(CJLabelLinkModelBlock)longPressBlock;
/**
對文本中跟withString相同的文字配置富文本
@param attrStr NSAttributedString源
@param withString 需要設(shè)置的文本
@param sameStringEnable 文本中所有與withAttString相同的文字是否同步設(shè)置屬性祈搜,sameStringEnable=NO 時(shí)取文本中首次匹配的NSAttributedString
@param attributes 文本屬性
@return 返回新的NSMutableAttributedString
*/
+ (NSMutableAttributedString *)configureAttributedString:(NSAttributedString *)attrStr
withString:(NSString *)withString
sameStringEnable:(BOOL)sameStringEnable
attributes:(NSDictionary *)attributes;
/**
對文本中跟withString相同的文字配置富文本较店,指定的文字為可點(diǎn)擊鏈點(diǎn)!H菅唷梁呈!
@param attrStr NSAttributedString源
@param withString 需要設(shè)置的文本
@param sameStringEnable 文本中所有與withAttString相同的文字是否同步設(shè)置屬性,sameStringEnable=NO 時(shí)取文本中首次匹配的NSAttributedString
@param linkAttributes 鏈點(diǎn)文本屬性
@param activeLinkAttributes 點(diǎn)擊狀態(tài)下的鏈點(diǎn)文本屬性
@param parameter 鏈點(diǎn)自定義參數(shù)
@param clickLinkBlock 鏈點(diǎn)點(diǎn)擊回調(diào)
@param longPressBlock 長按點(diǎn)擊鏈點(diǎn)回調(diào)
@return 返回新的NSMutableAttributedString
*/
+ (NSMutableAttributedString *)configureLinkAttributedString:(NSAttributedString *)attrStr
withString:(NSString *)withString
sameStringEnable:(BOOL)sameStringEnable
linkAttributes:(NSDictionary *)linkAttributes
activeLinkAttributes:(NSDictionary *)activeLinkAttributes
parameter:(id)parameter
clickLinkBlock:(CJLabelLinkModelBlock)clickLinkBlock
longPressBlock:(CJLabelLinkModelBlock)longPressBlock;
/**
* 移除制定range的點(diǎn)擊鏈點(diǎn)
*
* @param range 移除鏈點(diǎn)位置
*
* @return 返回新的NSAttributedString
*/
- (NSAttributedString *)removeLinkAtRange:(NSRange)range;
/**
* 移除所有點(diǎn)擊鏈點(diǎn)
*
* @return 返回新的NSAttributedString
*/
- (NSAttributedString *)removeAllLink;
@end
CJLabel支持CocoaPods安裝
platform :ios, '7.0'
target 'CJLabelDemo' do
pod 'CJLabel', '~> 2.1.3'
end
更多實(shí)現(xiàn)細(xì)節(jié)請看Demo
附:
字形與字符的相關(guān)描述引用自 http://blog.cnbang.net/tech/2729/