iOS开发封装一个可以响应超链接的label——基于RCLabel的交互扩展
一、引言
iOS系统是一个十分注重用户体验的系统,在iOS系统中,用户交互的方案也十分多,然而要在label中的某部分字体中添加交互行为确实不容易的,如果使用其他类似Button的控件来模拟,文字的排版又将是一个解决十分困难的问题。这个问题的由来是项目中的一个界面中有一些广告位标签,而这些广告位的标签却是嵌在文本中的,当用户点击文字标签的位置时,会跳转到响应的广告页。
CoreText框架和一些第三方库可以解决这个问题,但直接使用CoreText十分复杂,第三方库多注重于富文本的排版,对类似文字超链接的支持亦不是特别简洁,我们可以借助一些第三方的东西进行针对性更强,更易用的封装。
RCLabel是一个第三方的将html字符串进行文本布局的工具,代码十分轻巧,并且其是基于CoreText框架的,其原生性和扩展性十分强。在以前的一篇博客中,我将RCLabel进行了一些改进,使其支持异步加载远程图片,并且提供了更加简洁的面向应用的方法,博客地址如下:
扩展于RCLabel的支持异步加载网络图片的富文本引擎的设计:http://my.oschina.net/u/2340880/blog/499311 。
本篇博文,将在其基础上,完成设计一个可以支持文本超链接的文字视图。
二、视图类与模型类的设计
RCLabel的核心之处在于将HTML文本转换为富文本布局视图,因此我们可以将要显示的文本编程html字符串,将其可以进行用户交互的部分进行html超链接关联,RCLabel就检测到我们点击的区域进行响应逻辑的回调。设计类如下:
.h文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
//文本与超链接地址关联的model类 后面会说
@
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文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
@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
|
上面我们有用到一个YHBaseLinkingLabelModel类,这个类进行了链接与字符的映射,设计如下:
1
2
3
4
5
6
7
8
9
10
11
|
@interface YHBaseLinkingLabelModel : YHBaseModel
/**
*文字内容
*/
@property(nonatomic,strong)NSString * text;
/**
*超链接地址 nil则为无
*/
@property(nonatomic,strong)NSString * linking;
@end
|
YHBaseHtmlView类是对RCLabel的一层封装,其中也对RCLabel进行了一些优化和改动,代码较多且在上篇博客中有介绍,这里不再多做解释了。
在ViewController中写如下代码进行使用:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
- (
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);
}
|
运行效果如下:
效果不错,并且十分简单易用,对吧。