IOS體系是一個非常重視用戶體驗的體系,在IOS體系中,用戶交互的計劃也非常多,但是要在label中的某部門字體中添加交互行動確切不輕易的,假如應用其他相似Button的控件來模仿,文字的排版又將是一個處理好不容易的成績。這個成績的由來是項目中的一個界面中有一些告白位標簽,而這些告白位的標簽倒是嵌在文本中的,當用戶點擊文字標簽的地位時,會跳轉到呼應的告白頁。
CoreText框架和一些第三方庫可以處理這個成績,但直接應用CoreText非常龐雜,第三方庫多重視於富文本的排版,對相似文字超鏈接的支撐亦不是特殊簡練,我們可以借助一些第三方的器械停止針對性更強,更容易用的封裝。
RCLabel是一個第三方的將html字符串停止文本結構的對象,代碼非常輕盈,而且其是基於CoreText框架的,其原素性和擴大性非常強。
1、擴大於RCLabel的支撐異步加載收集圖片的富文本引擎的設計
在IOS開辟中,圖文混排一向都是UI編程的一個焦點點,也有很多優良的第三方引擎,個中很著名的一套圖文混排的框架叫做DTCoreText。然則在前些日的做的一個項目中,我並沒有采取這套框架,緣由有二,一是這套框架體積異常年夜,而項目標需求其實其實不太高;二是要在這套框架中修正一些器械,難度也異常年夜,我終究采取的是一個叫做RCLabel的第三方控件,經由一些簡略的優化和完美,到達了項目標請求。
先來引見一下我項目中的圖文混排的需求:起首我從辦事器中取到的數據是字符串,然則個中交叉圖片的地位是一個HTML的圖片標簽,標簽裡的資本途徑就是圖片的要求地址。須要到達的請求是這些數據顯示出來後,圖片的地位要空出來,然後經由過程異步的收集要求獲得圖片的數據,再將圖片拔出文字中。
要本身完成一套如許的引擎確切會比擬費事,榮幸的是RCLabel可以完善的幫我們解析帶有HTML標簽的數據,停止圖文混排,我們先來看一下這個器械怎樣用,上面是我封裝的一個展現html數據的view:
RCLabel的用法很簡略,總結來講只要三步:
@interface YHBaseHtmlView()<YHRTLabelImageDelegate>
{
//RCLabel對象
RCLabel * _rcLabel;
//保留屬性 用於異步加載完成後刷新
RTLabelComponentsStructure * _origenComponent;
//含html標簽的數據字符串
NSString * _srt;
}
@end
@implementation YHBaseHtmlView
/*
// Only override drawRect: if you perform custom draWing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
// DraWing code
}
*/
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self) {
//將rclabel初始化
_rcLabel = [[RCLabel alloc]init];
[self addSubview:_rcLabel];
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
_rcLabel = [[RCLabel alloc]initWithFrame:frame];
[self addSubview:_rcLabel];
}
return self;
}
-(void)reSetHtmlStr:(NSString *)htmlStr{
_srt = htmlStr;
//這個署理是我額定添加的 前面說明
_rcLabel.imageDelegate=self;
//設置frame
_rcLabel.frame=CGRectMake(0, 0, self.frame.size.width, 0);
//設置屬性
_origenComponent = [RCLabel extractTextStyle:htmlStr IsLocation:NO withRCLabel:_rcLabel];
_rcLabel.componentsAndPlainText = _origenComponent;
//獲得排版後的size
CGSize size = [_rcLabel optimumSize];
//從新設置frame
_rcLabel.frame=CGRectMake(0, 0, _rcLabel.frame.size.width, size.height);
self.frame=CGRectMake(self.frame.origin.x, self.frame.origin.y, _rcLabel.frame.size.width, size.height);
}
//這是我額定添加的署理辦法的完成
-(void)YHRTLabelImageSuccess:(RCLabel *)label{
_origenComponent = [RCLabel extractTextStyle:_srt IsLocation:NO withRCLabel:_rcLabel];
_rcLabel.componentsAndPlainText = _origenComponent;
CGSize size = [_rcLabel optimumSize];
_rcLabel.frame=CGRectMake(0, 0, _rcLabel.frame.size.width, size.height);
self.frame=_rcLabel.frame;
if ([self.delegate respondsToSelector:@selector(YHBaseHtmlView:SizeChanged:)]) {
[self.delegate YHBaseHtmlView:self SizeChanged:self.frame.size];
}
}
1.初始化並設置frame
2.經由過程帶html標簽的數據停止屬性的初始化
3.將屬性停止set設置偏重設視圖frame
RCLabel是很壯大,而且代碼很簡潔,然則個中處置圖片的部門必需是當地的圖片,即圖片html標簽中的途徑必需是當地圖片的名字,其外部是經由過程[UIImage ImageNamed:]這個辦法停止圖片的襯著的,所以要到達我們的須要,我們須要對其停止一些簡略的擴大:
1、在屬性設置辦法中添加一個參數,來辨別當地圖片與收集圖片:
//我在這個辦法中添加了location這個bool值,現實上rclabel這個參數也是我添加的,是為了前面署理應用的
2、在完成辦法中添加以下代碼,由於原文件有1900多行,在個中弄清晰邏輯關系也確切費了我不小的力量,我這裡只將我添加的代碼貼過去
+ (RTLabelComponentsStructure*)extractTextStyle:(NSString*)dataimage IsLocation:(BOOL)location withRCLabel:(RCLabel *)rcLabel;
#warning 這裡停止了兼容性處置
if (location) {
//當地圖片的襯著
if (tempURL) {
UIImage *tempImg = [UIImage imageNamed:tempURL];
component.img = tempImg;
}
}else{//這裡做長途圖片數據的處置
//這裡我停止了緩存的操作,這個緩存中間是我封裝的框架中的另外一套器械,這裡可以不消在乎
//先讀緩存
NSData * ceche = [[YHBaseCecheCenter sharedTheSingletion] readCecheFile:tempURL fromPath:YHBaseCecheImage];
if (ceche) {
UIImage * tempImg = [UIImage imageWithData:ceche];
component.img=tempImg;
}else{
//在分線程中停止圖片數據的獲得
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
if (tempURL) {
NSData * data = [YHBaseData getDataWithUrl:tempURL];
if (data) {
//獲得完成後村緩存
//做緩存
[[YHBaseCecheCenter sharedTheSingletion]writeCecheFile:data withFileID:tempURL toPath:YHBaseCecheImage];
//賦值 回調署理
UIImage * tempImg = [UIImage imageWithData:data];
component.img=tempImg;
//這裡署理是我添加的,當圖片下載完成後 告訴視圖從新排版
if ([[rcLabel imageDelegate]respondsToSelector:@selector(YHRTLabelImageSuccess:)]) {
//在主線程中履行回調
//這個處所要在主線程中履行,不然刷新會有延時
dispatch_async(dispatch_get_main_queue(), ^{
[[rcLabel imageDelegate] YHRTLabelImageSuccess:rcLabel];
});
}
}
};
});
}
}
2、視圖類與模子類的設計
RCLabel的焦點的地方在於將HTML文本轉換為富文本結構視圖,是以我們可以將要顯示的文本編程html字符串,將其可以停止用戶交互的部門停止html超鏈接聯系關系,RCLabel就檢測到我們點擊的區域停止呼應邏輯的回調。設計類以下:
.h文件
//文本與超鏈接地址聯系關系的model類 前面會說
下面我們有效到一個YHBaseLinkingLabelModel類,這個類停止了鏈接與字符的映照,設計以下:
@class YHBaseLinkingLabelModel;
@protocol YHBaseLinkingLabelProtocol <NSObject>
@optional
/**
*點擊超鏈接後動身的署理辦法 model中有鏈接地址和文字
*/
-(void)YHBaseLinkingLabelClickLinking:(YHBaseLinkingLabelModel *)model;
/**
*尺寸轉變後動身的辦法
*/
-(void)YHBaseLinkingLabelSizeChange:(CGSize)size;
@end
@interface YHBaseLinkingLabel : YHBaseView
/**
*文字數組 外面寄存這文字對應的超鏈接對象
*/
@property(nonatomic,strong)NSArray<YHBaseLinkingLabelModel *> * textArray;
@property(nonatomic,weak)id<YHBaseLinkingLabelProtocol>delegate;
/**
*設置文字色彩
*/
@property(nonatomic,strong)UIColor * textColor;
/**
*設置超鏈接文字色彩
*/
@property(nonatomic,strong)UIColor * linkColor;
/**
*設置字體年夜小
*/
@property(nonatomic,assign)NSUInteger fontSize;
/**
*設置超鏈接字體年夜小
*/
@property(nonatomic,assign)int linkingFontSize;
/**
*設置能否顯示下劃線
*/
@property(nonatomic,assign)BOOL isShowUnderLine;
@end
.m文件
@interface YHBaseLinkingLabel()<YHBaseHtmlViewProcotop>
@end
@implementation YHBaseLinkingLabel
{
//之前博客中 封裝的顯示HTML字符串富文本的視圖
YHBaseHtmlView * _label;
}
/*
// 重載一些初始化辦法
- (instancetype)init
{
self = [super init];
if (self) {
_label = [[YHBaseHtmlView alloc]init];
[self addSubview:_label];
[_label mas_makeConstraints:^(MASConstraintMaker *make) {
make.leading.equalTo(@0);
make.trailing.equalTo(@0);
make.top.equalTo(@0);
make.bottom.equalTo(@0);
}];
_label.delegate=self;
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self) {
_label = [[YHBaseHtmlView alloc]init];
[self addSubview:_label];
[_label mas_makeConstraints:^(MASConstraintMaker *make) {
make.leading.equalTo(@0);
make.trailing.equalTo(@0);
make.top.equalTo(@0);
make.bottom.equalTo(@0);
}];
_label.delegate=self;
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
_label = [[YHBaseHtmlView alloc]init];
[self addSubview:_label];
[_label mas_makeConstraints:^(MASConstraintMaker *make) {
make.leading.equalTo(@0);
make.trailing.equalTo(@0);
make.top.equalTo(@0);
make.bottom.equalTo(@0);
}];
_label.delegate=self;
}
return self;
}
//設置文本數組
-(void)setTextArray:(NSArray<YHBaseLinkingLabelModel *> *)textArray{
_textArray = textArray;
//停止html轉換
NSString * htmlString = [self transLinkingDataToHtmlStr:textArray];
//停止結構
[_label reSetHtmlStr:htmlString];
}
-(void)setTextColor:(UIColor *)textColor{
_textColor = textColor;
_label.fontColor = textColor;
}
-(void)setLinkColor:(UIColor *)linkColor{
_linkColor = linkColor;
_label.linkingColor = linkColor;
}
-(void)setFontSize:(NSUInteger)fontSize{
_fontSize = fontSize;
[_label setFontSize:(int)fontSize];
}
-(void)setLinkingFontSize:(int)linkingFontSize{
_linkingFontSize = linkingFontSize;
[_label setLinkingSize:linkingFontSize];
}
-(void)setIsShowUnderLine:(BOOL)isShowUnderLine{
_isShowUnderLine = isShowUnderLine;
[_label setShowUnderLine:isShowUnderLine];
}
-(NSString *)transLinkingDataToHtmlStr:(NSArray<YHBaseLinkingLabelModel *> *)data{
NSMutableString * mutStr = [[NSMutableString alloc]init];
for (int i=0; i<data.count; i++) {
//這個model中寄存的是超鏈接部門的文字和對應的url
YHBaseLinkingLabelModel * model = data[i];
if (!model.linking) {
[mutStr appendString:model.text];
}else {
[mutStr appendString:@"<a href="];
[mutStr appendString:model.linking];
[mutStr appendString:@">"];
[mutStr appendString:model.text];
[mutStr appendString:@"</a>"];
}
}
return mutStr;
}
#pragma mark delegate
//點擊的回調
-(void)YHBaseHtmlView:(YHBaseHtmlView *)htmlView ClickLink:(NSString *)url{
for (YHBaseLinkingLabelModel * model in _textArray) {
if ([model.linking isEqualToString:url]) {
if ([self.delegate respondsToSelector:@selector(YHBaseLinkingLabelClickLinking:)]) {
[self.delegate YHBaseLinkingLabelClickLinking:model];
return;
}
}
}
}
//結構尺寸轉變的回調
-(void)YHBaseHtmlView:(YHBaseHtmlView *)htmlView SizeChanged:(CGSize)size{
if ([self.delegate respondsToSelector:@selector(YHBaseLinkingLabelSizeChange:)]) {
[self.delegate YHBaseLinkingLabelSizeChange:size];
}
}
@end
@interface YHBaseLinkingLabelModel : YHBaseModel
YHBaseHtmlView類是對RCLabel的一層封裝,個中也對RCLabel停止了一些優化和修改,代碼較多且在上篇博客中有引見,這裡不再多做說明了。
/**
*文字內容
*/
@property(nonatomic,strong)NSString * text;
/**
*超鏈接地址 nil則為無
*/
@property(nonatomic,strong)NSString * linking;
@end
在ViewController中寫以下代碼停止應用:
- (void)viewDidLoad {
運轉後果以下:
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
YHBaseLinkingLabel * label = [[YHBaseLinkingLabel alloc]initWithFrame:CGRectMake(100, 100, 200, 100)];
NSMutableArray * array = [[NSMutableArray alloc]init];
for (int i=0; i<6; i++) {
YHBaseLinkingLabelModel * model = [[YHBaseLinkingLabelModel alloc]init];
if (!(i%2)) {
model.text =[NSString stringWithFormat:@"第%d個標簽",i];
model.linking = [NSString stringWithFormat:@"第%d個標簽",i];
}else{
model.text = @",不克不及點得文字,";
}
[array addObject:model];
}
label.textColor = [UIColor blackColor];
label.linkColor = [UIColor purpleColor];
label.fontSize = 15;
label.linkingFontSize = 17;
label.isShowUnderLine=YES;
label.delegate=self;
label.textArray = array;
[self.view addSubview:label];
}
-(void)YHBaseLinkingLabelClickLinking:(YHBaseLinkingLabelModel *)model{
NSLog(@"%@",model.linking);
}
後果不錯,而且非常簡略易用,對吧。
【iOS App開辟中擴大RCLabel組件停止基於HTML的文本結構】的相關資料介紹到這裡,希望對您有所幫助! 提示:不會對讀者因本文所帶來的任何損失負責。如果您支持就請把本站添加至收藏夾哦!