最近设计同学终于受不了商品评价列表中的评价内容没有行间距,强迫我们必须加上行间距。
当时我就感觉一阵头大,因为这个评价内容如果超过五行的话,是默认不显示的,当用户点击展开才会显示,这样的话我就要在计算行数的时候把行间距算进去,还有一行的时候如果是中文是不能给Label加行间距的,否则一行文字下面会片空白,当然高度的计算也要去掉行间距。下面就详细讲一下如果解决这些问题。
通过boundingWithRect获取文本的高度
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
NSString *text = @"UILabel中文带行间距的处理,限制行数,计算高度等";
NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:text];
NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
style.lineSpacing = 10;
[attributeString addAttribute:NSParagraphStyleAttributeName
value:style
range:NSMakeRange(0, text.length)];
[attributeString addAttribute:NSFontAttributeName
value:[UIFont systemFontOfSize:14]
range:NSMakeRange(0, text.length)];
NSStringDrawingOptions options = NSStringDrawingUsesLineFragmentOrigin |
NSStringDrawingUsesFontLeading;
CGRect rect = [attributeString boundingRectWithSize:CGSizeMake(100, MAXFLOAT)
options:options
context:nil];
|
中文富文本有行间距的坑
- 计算文字高度的坑:上面计算方式在计算带有中文,并且有行间距的富文本时,会出现在计算一行时,文本高度不对,多了一个行间距的高度。但在计算纯英文时却不会存在这个情况。这样会导致在存在父控件时,父控件整体高度计算不对。
- 给Label设置文本的坑:在给Label设置富文本时,如果是一行并且带中文,并且设置了间距lineSpace,结果多发现显示出来多了一个间距的高度。
解决方案
- 判断行数与是否存在中文,当行数为一行,并且存在中文时,需要将计算结果的高度减去行间距。此时才为正确文本正确高度。
- 需要判断是否超过一行,超过一行则设置富文本的lineSpace。
下面是封装好的方法,可以直接给NSString创建一个category,把以下方法拷贝进去。
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
|
/**
* 计算文字高度,可以处理计算带行间距的
*/
- (CGSize)boundingRectWithSize:(CGSize)size
font:(UIFont*)font
lineSpacing:(CGFloat)lineSpacing
{
NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:self];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineSpacing = lineSpacing;
[attributeString addAttribute:NSParagraphStyleAttributeName
value:paragraphStyle
range:NSMakeRange(0, self.length)];
[attributeString addAttribute:NSFontAttributeName
value:font
range:NSMakeRange(0, self.length)];
NSStringDrawingOptions options = NSStringDrawingUsesLineFragmentOrigin |
NSStringDrawingUsesFontLeading;
CGRect rect = [attributeString boundingRectWithSize:size
options:options
context:nil];
//文本的高度减去字体高度小于等于行间距,判断为当前只有1行
if ((rect.size.height - font.lineHeight) <= paragraphStyle.lineSpacing)
{
if ([self containChinese:self])
{ //如果包含中文
rect = CGRectMake(rect.origin.x,
rect.origin.y,
rect.size.width,
rect.size.height-paragraphStyle.lineSpacing);
}
}
return rect.size;
}
//判断如果包含中文
- (BOOL)containChinese:(NSString *)str
{
for(int i=0; i< [str length];i++)
{
int a = [str characterAtIndex:i];
if(a > 0x4e00 && a < 0x9fff)
{
return YES;
}
}
return NO;
}
/**
* 计算最大行数文字高度,可以处理计算带行间距的
*/
- (CGFloat)boundingRectWithSize:(CGSize)size
font:(UIFont*)font
lineSpacing:(CGFloat)lineSpacing
maxLines:(NSInteger)maxLines
{
if (maxLines <= 0)
{
return 0;
}
CGFloat maxHeight = font.lineHeight * maxLines + lineSpacing * (maxLines - 1);
CGSize orginalSize = [self boundingRectWithSize:size
font:font
lineSpacing:lineSpacing];
if (orginalSize.height >= maxHeight)
{
return maxHeight;
}
else
{
return orginalSize.height;
}
}
/**
* 计算是否超过一行 用于给Label 赋值attribute text的时候 超过一行设置lineSpace
*/
- (BOOL)isMoreThanOneLineWithSize:(CGSize)size
font:(UIFont *)font
lineSpaceing:(CGFloat)lineSpacing
{
if ([self boundingRectWithSize:size
font:font
lineSpacing:lineSpacing].height > font.lineHeight)
{
return YES;
}
else
{
return NO;
}
}
|