Label設(shè)置行間距

Label設(shè)置行間距

內(nèi)容摘要

  • UILabel顯示多行文本
  • UILabel設(shè)置行間距
  • 解決單行文本 & 多行文本顯示的問題

場(chǎng)景描述

  • 眾所周知,UILabel顯示多行的話,默認(rèn)行間距為0,但實(shí)際開發(fā)中,如果顯示多行文本,一般情況下會(huì)有一定的行間距。如果想動(dòng)態(tài)調(diào)整行間距,則需要賦值富文本屬性(而不是文本屬性

問題分析

Label顯示多行文本

  • label默認(rèn)情況下,只會(huì)顯示單行文本,主要是因?yàn)樗?code>numberOfLines屬性值是1;如果要顯示多行,把這個(gè)屬性值改成0即可。
self.lblResult.numberOfLines = 0;
  • 默認(rèn)情況下,會(huì)顯示成這樣:


    Label設(shè)置行間距_多行0間距.png
  • 如果想添加行間距,你可能會(huì)這樣做:
    • 寫一個(gè)string轉(zhuǎn)換成AttributedString的方法(或者給字符串增加一個(gè)分類)
    -(NSAttributedString *)getAttributedStringWithString:(NSString *)string lineSpace:(CGFloat)lineSpace {
        NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:string];
        NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
        paragraphStyle.lineSpacing = lineSpace; // 調(diào)整行間距
        NSRange range = NSMakeRange(0, [string length]);
        [attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:range];
        return attributedString;
    

}
* 賦值富文本屬性 objc
NSString string = @"眾所周知,UILabel顯示多行的話,默認(rèn)行間距為0,但實(shí)際開發(fā)中,如果顯示多行文本,一般情況下會(huì)有一定的行間距。如果想動(dòng)態(tài)調(diào)整行間距,則需要賦值富文本屬性*(而不是文本屬性)";
// 5:行間距
self.lblResult.attributedText = [self getAttributedStringWithString:string lineSpace:5];
```

  • 結(jié)果如下圖:


    Label設(shè)置行間距_多行5間距.png

    =============== 華麗的分割線 ===============
    </br>

問題:以上方法顯示多行文本貌似沒有問題,但如果文本只有一行呢?

Label顯示單行文本

  • 顯示單行中文:
NSString *string = @"文本只有一行會(huì)顯示什么樣?";
self.lblResult.attributedText = [self getAttributedStringWithString:string lineSpace:5];
Label設(shè)置行間距_單行中文5間距.png
  • 顯示單行英文:
NSString *string = @"good good study day day up";
self.lblResult.attributedText = [self getAttributedStringWithString:string lineSpace:5];
Label設(shè)置行間距_單行英文5間距1.png
  • 通過比較發(fā)現(xiàn),用同樣的方法,單行顯示中文 & 英文,效果不同,中文會(huì)多了一些空白!心中立馬有種蛋蛋的憂桑,一絲絲凄涼……

遇到問題之后

  • 查詢API-NSMutableParagraphStyle

// Indent:縮進(jìn)
@property(NS_NONATOMIC_IOSONLY) CGFloat lineSpacing;
@property(NS_NONATOMIC_IOSONLY) CGFloat paragraphSpacing;
@property(NS_NONATOMIC_IOSONLY) NSTextAlignment alignment;
@property(NS_NONATOMIC_IOSONLY) CGFloat firstLineHeadIndent;
@property(NS_NONATOMIC_IOSONLY) CGFloat headIndent;
@property(NS_NONATOMIC_IOSONLY) CGFloat tailIndent;
@property(NS_NONATOMIC_IOSONLY) NSLineBreakMode lineBreakMode;
@property(NS_NONATOMIC_IOSONLY) CGFloat minimumLineHeight;
@property(NS_NONATOMIC_IOSONLY) CGFloat maximumLineHeight;
@property(NS_NONATOMIC_IOSONLY) NSWritingDirection baseWritingDirection;
@property(NS_NONATOMIC_IOSONLY) CGFloat lineHeightMultiple;
@property(NS_NONATOMIC_IOSONLY) CGFloat paragraphSpacingBefore;
@property(NS_NONATOMIC_IOSONLY) float hyphenationFactor;
```

  • 各種嘗試之后,問題還在那兒……
  • 想到富文本屬性,查詢NSAttributedString.h頭文件
    • 仿佛看到了勝利的曙光
    UIKIT_EXTERN NSString * const NSBaselineOffsetAttributeName NS_AVAILABLE(10_0, 7_0);      // NSNumber containing floating point value, in points; offset from baseline, default 0
    

嘗試解決問題

  • 重構(gòu)getAttributedStringWithString方法
-(NSAttributedString *)getAttributedStringWithString:(NSString *)string lineSpace:(CGFloat)lineSpace baselineOffset:(CGFloat)baselineOffset {
    NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:string];
    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
    paragraphStyle.lineSpacing = lineSpace; // 調(diào)整行間距
    NSRange range = NSMakeRange(0, [string length]);
    [attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:range];
    // 設(shè)置文本偏移量
    [attributedString addAttribute:NSBaselineOffsetAttributeName value:@(baselineOffset) range:range];
    return attributedString;
}
  • 于是單行文本顯示成這樣:


    Label設(shè)置行間距_單行中文5間距偏移量.png

    Label設(shè)置行間距_單行英文5間距偏移量.png
  • 那么多行呢?


    Label設(shè)置行間距_多行中文5間距偏移量.png

    Label設(shè)置行間距_多行英文5間距偏移量.png

    我擦!

問題分析

  • 通過上面的示例分析,可以簡(jiǎn)單的得到結(jié)論:
    • 未設(shè)置行間距和偏移量,什么問題都沒有,只是行與行之間顯示得比較緊促!
    • 只設(shè)置行間距,多行和單行英文情況下,顯示沒有問題,但單行中文顯示會(huì)有問題,底部會(huì)有空白!
    • 既設(shè)置行間距,也設(shè)置偏移的情況下,單行顯示沒有問題,但多行顯示有問題!

解決辦法

  • 多行情況下,不設(shè)置偏移!

那么問題來了,如何判斷l(xiāng)abel顯示幾行呢?

  • 筆者用比較笨的方法:計(jì)算某幾個(gè)固定字符的高度,然后再計(jì)算label文本的高度,如果后者大于前者,則為多行!
  • 示例代碼如下:
CGFloat lineSpace = 5;
CGFloat offset = -(1.0/3 * lineSpace) - 1.0/3;
CGFloat marginLeft = 20;
CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width;
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineSpacing = lineSpace; // 調(diào)整行間距
NSDictionary *attrs = @{
                            NSFontAttributeName : self.lblResult.font,
                            NSParagraphStyleAttributeName : paragraphStyle
                            };
// 計(jì)算一行文本的高度
CGFloat oneHeight = [@"測(cè)試Test" boundingRectWithSize:CGSizeMake(screenWidth-marginLeft*2, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:attrs context:nil].size.height;
CGFloat rowHeight = [self.txtInputString.text boundingRectWithSize:CGSizeMake(screenWidth-marginLeft*2, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:attrs context:nil].size.height;
// 如果超出一行,則offset=0;
offset = rowHeight > oneHeight ? 0 : offset;
self.lblResult.attributedText = [self getAttributedStringWithString:self.txtInputString.text lineSpace:lineSpace baselineOffset:offset];
  • OK,這樣貌似解決了上面的問題,但細(xì)心的你估計(jì)會(huì)發(fā)現(xiàn)一個(gè)問題:CGFloat offset = -(1.0/3 * lineSpace) - 1.0/3;這行代碼是什么意思?

關(guān)于 f(x) = -(1.0/3 * x) - 1.0/3

  • offset是通過窮舉法歸納總結(jié)出來的,也許不夠準(zhǔn)確,但在項(xiàng)目中用起來挺好。
  • 根據(jù)文本內(nèi)容,描點(diǎn)
// 描點(diǎn)
CGPoint points[15];
// CGPointMake(lineSpace, offset)
points[0] = CGPointMake(5, -2);
points[1] = CGPointMake(8, -3);
points[2] = CGPointMake(10, -3.5);
points[3] = CGPointMake(16, -6);
points[4] = CGPointMake(20, -7);
points[5] = CGPointMake(25, -9);
points[6] = CGPointMake(30, -11);
points[7] = CGPointMake(35, -11.5);
points[8] = CGPointMake(40, -13);
points[9] = CGPointMake(50, -15);
points[10] = CGPointMake(60, -18.5);
points[11] = CGPointMake(70, -23);
points[12] = CGPointMake(80, -26);
points[13] = CGPointMake(90, -29);
points[14] = CGPointMake(100, -32);
// 畫線
[self drawLine:points count:15];
  • 畫線
// 畫線
-(void)drawLine:(CGPoint[])points count:(NSInteger)count {
    CGMutablePathRef linePath = CGPathCreateMutable();
    CGPathAddLines(linePath, NULL, points, count);
    // 關(guān)聯(lián)layer和貝塞爾路徑
    self.linesLayer.path = linePath;
    CGPathRelease(linePath);
    // 創(chuàng)建Animation
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
    animation.fromValue = @(0.0);
    animation.toValue = @(1.0);
    self.linesLayer.autoreverses = NO;
    animation.duration = 1.5f;
    // 設(shè)置layer的animation
    [self.linesLayer addAnimation:animation forKey:nil];
    self.linesLayer.strokeEnd = 1;
}
![Uploading Label設(shè)置行間距_歸納總結(jié)offset的算法_323780.png . . .]
Label設(shè)置行間距_歸納總結(jié)offset的算法.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容