富文本帶點擊事件的解決方案
效果
分析
富文本中要添加點擊link事件,需要深入到CoreText里面才能夠解決,本人將TTTAttributedLabel進行了封裝(封裝並不完全,以后會繼續完善),簡化了操作.
源碼
https://github.com/YouXianMing/UI-Component-Collection
https://github.com/TTTAttributedLabel/TTTAttributedLabel
// // TTTAttributeLabelView.h // TappedLabel // // Created by YouXianMing on 15/6/13. // Copyright (c) 2015年 YouXianMing. All rights reserved. // #import <UIKit/UIKit.h> #import <Foundation/Foundation.h> #import <CoreText/CoreText.h> @class TTTAttributeLabelView; @protocol TTTAttributeLabelViewDelegate <NSObject> @optional /** * 獲取超鏈接點擊事件 * * @param attributeLabelView 實例對象 * @param flag 設置的被點擊的flag */ - (void)TTTAttributeLabelView:(TTTAttributeLabelView *)attributeLabelView linkFlag:(NSString *)flag; @end @interface TTTAttributeLabelView : UIView /** * 代理 */ @property (nonatomic, weak) id <TTTAttributeLabelViewDelegate> delegate; /** * 輸入的富文本 */ @property (nonatomic, strong) NSAttributedString *attributedString; /** * 通常狀態鏈接顏色 + 通常狀態鏈接下划線樣式 + 點擊鏈接時鏈接顏色 + 點擊鏈接時下划線樣式 */ @property (nonatomic, strong) UIColor *linkColor; @property (nonatomic) CTUnderlineStyle linkUnderLineStyle; // 默認值為kCTUnderlineStyleNone @property (nonatomic, strong) UIColor *activeLinkColor; @property (nonatomic) CTUnderlineStyle activelinkUnderLineStyle; // 默認值為kCTUnderlineStyleNone /** * 添加超鏈接文本的文本range * * @param linkStringRange 超鏈接文本的文本range * @param flag 該文本的標記 */ - (void)addLinkStringRange:(NSRange)linkStringRange flag:(NSString *)flag; /** * 重置 */ - (void)reset; /** * 渲染文本 */ - (void)render; /** * 重新計算尺寸 */ - (void)resetSize; /** * 計算執行resetSize后的size * * @param attributedString 富文本 * @param width 給定一個寬度 * * @return 計算好的size */ + (CGSize)sizeThatFitsAttributedString:(NSAttributedString *)attributedString withFixedWidth:(CGFloat)width; @end
// // TTTAttributeLabelView.m // TappedLabel // // Created by YouXianMing on 15/6/13. // Copyright (c) 2015年 YouXianMing. All rights reserved. // #import "TTTAttributeLabelView.h" #import "TTTAttributedLabel.h" /** * 將CFString轉換為NSString * * @param cfString * * @return 轉換后的CFString */ static inline NSString* nsStringWithCfString(CFStringRef cfString) { return (__bridge NSString *)cfString; } /*--------------------------------------------------------------------------------*/ @interface RangeFlag : NSObject @property (nonatomic, strong) NSString *flag; @property (nonatomic) NSRange range; + (RangeFlag *)rangeFlagWithFlag:(NSString *)flag range:(NSRange)range; @end @implementation RangeFlag + (RangeFlag *)rangeFlagWithFlag:(NSString *)flag range:(NSRange)range { RangeFlag *rangeFlag = [RangeFlag new]; rangeFlag.flag = flag; rangeFlag.range = range; return rangeFlag; } @end /*--------------------------------------------------------------------------------*/ @interface TTTAttributeLabelView () <TTTAttributedLabelDelegate> @property (nonatomic, strong) TTTAttributedLabel *label; @property (nonatomic, strong) NSMutableArray *links; @end @implementation TTTAttributeLabelView - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [self setup]; } return self; } - (void)setup { // 存儲超鏈接的數組 self.links = [NSMutableArray array]; // label self.label = [[TTTAttributedLabel alloc] initWithFrame:self.bounds]; self.label.delegate = self; self.label.extendsLinkTouchArea = NO; self.label.verticalAlignment = TTTAttributedLabelVerticalAlignmentTop; self.label.numberOfLines = 0; [self addSubview:self.label]; } - (void)reset { self.label.text = nil; [self.links removeAllObjects]; } - (void)render { if (self.attributedString.string.length <= 0) { return; } self.label.text = self.attributedString; [self linkStyles]; [self addLinks]; } - (void)addLinks { for (int count = 0; count < self.links.count; count++) { RangeFlag *rangeflag = self.links[count]; [self.label addLinkToURL:[NSURL URLWithString:rangeflag.flag] withRange:rangeflag.range]; } } - (void)linkStyles { UIColor *linkColor = (self.linkColor == nil ? [UIColor blueColor] : self.linkColor); CTUnderlineStyle linkUnderLineStyle = [self checkEnumValueValid:self.linkUnderLineStyle]; UIColor *activeLinkColor = (self.activeLinkColor == nil ? [UIColor redColor] : self.activeLinkColor); CTUnderlineStyle activelinkUnderLineStyle = [self checkEnumValueValid:self.activelinkUnderLineStyle]; // 沒有點擊時候的樣式 self.label.linkAttributes = @{nsStringWithCfString(kCTForegroundColorAttributeName) : linkColor, nsStringWithCfString(kCTUnderlineStyleAttributeName) : [NSNumber numberWithInt:linkUnderLineStyle]}; // 點擊時候的樣式 self.label.activeLinkAttributes = @{nsStringWithCfString(kCTForegroundColorAttributeName) : activeLinkColor, nsStringWithCfString(kCTUnderlineStyleAttributeName) : [NSNumber numberWithInt:activelinkUnderLineStyle]}; } - (CTUnderlineStyle)checkEnumValueValid:(CTUnderlineStyle)style { if (style == kCTUnderlineStyleNone || style == kCTUnderlineStyleSingle || style == kCTUnderlineStyleThick || style == kCTUnderlineStyleDouble) { return style; } else { return kCTUnderlineStyleSingle; } } - (void)addLinkStringRange:(NSRange)linkStringRange flag:(NSString *)flag { [self.links addObject:[RangeFlag rangeFlagWithFlag:flag range:linkStringRange]]; } - (void)resetSize { [self.label sizeToFit]; CGFloat x = self.frame.origin.x; CGFloat y = self.frame.origin.y; CGFloat width = self.label.frame.size.width; CGFloat height = self.label.frame.size.height; self.frame = CGRectMake(x, y, width, height); } + (CGSize)sizeThatFitsAttributedString:(NSAttributedString *)attributedString withFixedWidth:(CGFloat)width { return [TTTAttributedLabel sizeThatFitsAttributedString:attributedString withConstraints:CGSizeMake(width, 0) limitedToNumberOfLines:0]; } #pragma mark - 超鏈接代理 - (void)attributedLabel:(TTTAttributedLabel *)label didSelectLinkWithURL:(NSURL *)url { if (_delegate && [_delegate respondsToSelector:@selector(TTTAttributeLabelView:linkFlag:)]) { [_delegate TTTAttributeLabelView:self linkFlag:url.absoluteString]; } } @end
使用
// // ViewController.m // TapLabelView // // Created by YouXianMing on 15/6/13. // Copyright (c) 2015年 YouXianMing. All rights reserved. // #import "ViewController.h" #import "TTTAttributeLabelView.h" #import "NSString+RichText.h" #import "TTTAttributedLabel.h" @interface ViewController () <TTTAttributeLabelViewDelegate> @property (nonatomic, strong) TTTAttributeLabelView *attributeLabelView; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor blackColor]; // 創建富文本 NSString *string = @"Between the husband and earth, each master. All Gou Fei Wu, although a little and Mo to take. YouXianMing but the river breeze, and the mountain of the moon, ear and sound, eyes meet and fineness. Take no ban, be inexhaustible. Is also the creator of the endless Tibet, and I and the children were appropriate.\n夫天地之間,物各有主。苟非吾之所有,雖一毫而莫取。惟江上之清風,與山間之明月,耳得之而為聲,目遇之而成色。 取之無禁,用之不竭。是造物者之無盡藏也,而吾與子之所共適。"; NSMutableParagraphStyle *style = [NSMutableParagraphStyle new]; style.lineSpacing = 4.f; style.paragraphSpacing = style.lineSpacing * 4; style.alignment = NSTextAlignmentCenter; NSAttributedString *attributedString = \ [string createAttributedStringAndConfig:@[[ConfigAttributedString foregroundColor:[UIColor whiteColor] range:string.range], [ConfigAttributedString paragraphStyle:style range:string.range], [ConfigAttributedString font:[UIFont fontWithName:@"AppleSDGothicNeo-UltraLight" size:14.f] range:string.range]]]; // 初始化對象 self.attributeLabelView = [[TTTAttributeLabelView alloc] initWithFrame:CGRectMake(10, 50, 300, 0)]; self.attributeLabelView.attributedString = attributedString; self.attributeLabelView.delegate = self; self.attributeLabelView.linkColor = [UIColor cyanColor]; // 添加超鏈接 NSRange range1 = [string rangeOfString:@"YouXianMing"]; [self.attributeLabelView addLinkStringRange:range1 flag:@"link1"]; NSRange range2 = [string rangeOfString:@"inexhaustible"]; [self.attributeLabelView addLinkStringRange:range2 flag:@"link2"]; NSRange range3 = [string rangeOfString:@"耳得之而為聲,目遇之而成色。"]; [self.attributeLabelView addLinkStringRange:range3 flag:@"link3"]; // 進行渲染 [self.attributeLabelView render]; [self.attributeLabelView resetSize]; [self.view addSubview:self.attributeLabelView]; } - (void)TTTAttributeLabelView:(TTTAttributeLabelView *)attributeLabelView linkFlag:(NSString *)flag { NSLog(@"%@", flag); } @end