前言
UILabel 是的使用頻率是非常頻繁,當文字較多的時候,會顯得密密麻麻的,不利於UI顯示及用戶觀看。通常我們需要對 Label 中“行間距”或“文字間距”進行調整,從而使文字沒那麼緊密,提高用戶體驗。
當調整“行間距”或“字間距”後,很多時候需要對 Label 進行高度自適應,此時會出現高度計算錯誤的問題,所以我們需要對“富文字”高度進行計算。計算結束後,經測試發現:當文字爲1行並且全部文字爲“中文”時,高度計算不準確,最後對該問題進行處理。
綜上所述:分爲以下三步進行設置“UILabel 內容的間距及高度的計算”
1. 通過使用 UILbael 的分類實現修改間距的功能。
2 .使用兩種方法來計算:“富文字”的高度。
3. 對“高度計算結果”特殊情況進行處理。
一.設置 Label “行間距”或“字間距”
設置思路
普通的 NSString 文字,不能調整字體“行間距”或“字間距”,但 NSAttributedString 富文字,可以調整該間距,所以我們把普通的字體變爲富文字,然後使用富文字對應方法即可設置間距。
設置過程
給 label 添加一個分類,在分類中聲明並實現三種方法
@interface UILabel (ChangeLineSpaceAndWordSpace)
//1.設置:行間距
+ (void)changeLineSpaceForLabel:(UILabel *)label WithSpace:(float)space;
//2.設置:字間距
+ (void)changeWordSpaceForLabel:(UILabel *)label WithSpace:(float)space;
//3.設置:行間距 與 字間距
+ (void)changeSpaceForLabel:(UILabel *)label withLineSpace:(float)lineSpace WordSpace:(float)wordSpace;
@end
1.設置:行間距
//傳入需要設置的 Label 與需要設置的行間距數值
- (void)changeLineSpaceForLabel:(UILabel *)label WithSpace:(float)space {
NSString *labelText = label.text;
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:labelText];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
[paragraphStyle setLineSpacing:space];
[attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [labelText length])];
label.attributedText = attributedString;
[label sizeToFit];
}
- (void)changeLineSpaceForLabel:(UILabel *)label WithSpace:(float)space {
2.設置:字間距
//傳入需要設置的 Label 與需要設置的字間距數值
- (void)changeWordSpaceForLabel:(UILabel *)label WithSpace:(float)space {
NSString *labelText = label.text;
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:labelText attributes:@{NSKernAttributeName:@(space)}];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
[attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [labelText length])];
label.attributedText = attributedString;
[label sizeToFit];
}
- (void)changeWordSpaceForLabel:(UILabel *)label WithSpace:(float)space {
3.同時設置: 行間距 與 字間距
//傳入需要設置的 Label 與需要設置的行間距數值與字間距數值
- (void)changeSpaceForLabel:(UILabel *)label withLineSpace:(float)lineSpace WordSpace:(float)wordSpace {
NSString *labelText = label.text;
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:labelText attributes:@{NSKernAttributeName:@(wordSpace)}];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
[paragraphStyle setLineSpacing:lineSpace];
[attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [labelText length])];
label.attributedText = attributedString;
[label sizeToFit];
}
- (void)changeSpaceForLabel:(UILabel *)label withLineSpace:(float)lineSpace WordSpace:(float)wordSpace {
使用示例
//設置 label 內容,將 lable 內容變爲有間距的內容
testLabel.text = @"測試文字測試文字測試文字測試文字測試文字測試文字測試文字測試文字測試文字測試文字測試文字測試文字測試文字測試文字測試文字";
[UILabel changeLineSpaceForLabel:testLabel WithSpace:20];//設置testLabel中內容的行間距爲20
[UILabel changeWordSpaceForLabel:self.testLabel WithSpace:20];//設置testLabel中內容的字間距爲20
//
[UILabel changeLineSpaceForLabel:self.testLabel WithSpace:20];//設置testLabel中內容的行間距爲20,字間距爲20
二.計算 Label 富文字高度
計算思路
可以直接計算富字體排布高度,該高度即爲 Label 高度,也可以使用 UILable 的方法來計算 Label 高度
方法1.使用 UILabel 方法:sizeThatFits
- (CGRect)sizeThatFits:(CGSize)size;
通過 UILabel 的方法 sizeThatFits,該方法需要傳入一個參數,即可算出目前label高度。
參數1. size:其中 size 的寬度爲 label 的寬度,size 的一般填入最大高度。
CGSize size = [label sizeThatFits:CGSizeMake(label.frame.size.width, CGFLOAT_MAX)];
方法2.使用 NSString 方法:boundingWithRect
- (CGRect)boundingRectWithSize:(CGSize)size
options:(NSStringDrawingOptions)options
context:(nullable NSStringDrawingContext *)context;
該方法需要傳入3個參數:
參數1. size:其中 size 的寬度爲 label 的寬度,size 的一般填入最大高度。
參數2. options: 文本繪製時的附加選項 1. NSStringDrawingUsesLineFragmentOrigin (整個文本將以每行組成的矩形爲單位計算整個文本的尺寸 ) 2. NSStringDrawingUsesFontLeading (使用字體的行間距來計算文本佔用的範圍,即每一行的底部到下一行的底部的距離計算 ) 3. NSStringDrawingUsesDeviceMetrics (將文字以圖像符號計算文本佔用範圍,而不是以字符計算。也即是以每一個字體所佔用的空間來計算文本範圍 ) 4. NSStringDrawingTruncatesLastVisibleLine (當文本不能適合的放進指定的邊界之內,則自動在最後一行添加省略符號。如果 NSStringDrawingUsesLineFragmentOrigin 沒有設置,則該選項不生效)
參數3. context: 上下文,一般傳nil
使用示例
NSStringDrawingOptions options = NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading;
CGRect rect = [attributeString boundingRectWithSize:CGSizeMake(label.frame.size.width, CGFLOAT_MAX) options:options context:nil];
三.Label富文字計算高度注意點
出現問題
當文字只有一行並且是全是中文時:高度計算不準確
解決思路
首先: 通過 sizeThatFits 或 boundingWithRect 計算出未處理的 rect 值
第一步: 對 rect 值,進行判斷: “是否只有一行 並且 該行文字全爲中文”
第二步: 修復高度值,對高度值進行調整: “減去一個行間距值”
示例代碼
//通過 boundingWithRect 計算出未處理的 rect 值
NSStringDrawingOptions options = NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading;
CGRect rect = [attributeString boundingRectWithSize:CGSizeMake(label.frame.size.width, CGFLOAT_MAX) options:options context:nil];
//判斷內容是否只有一行 : (目前高度 - 字體高度) <= 行間距
if ((rect.size.height - _font.lineHeight) <= paragraphStyle.lineSpacing){
//如果只有一行,進行判斷內容中是否全部爲漢字
if ([self containChinese:string]) {
//修正後高度爲: 目前高度 - 一個行間距
rect = CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height-paragraphStyle.lineSpacing);
}
}
//判斷內容中是否全部爲漢字
- (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;
}