Label设置行间距

一、前言
近来来了二个新安排,将App的风骨修改了一次。在展现文字时,扩充了行间距。原来感觉只是展现和测算中度的时候增添上富文本的lineSpace属性就可以,可是结果在呈现一行中文的时候,却怎么也算算字体的时候多了一个行间距的惊人,浮现的Label也多了二个行间距的可观。经过查找资料,网络也可能有人境遇同样的坑。计算高度时,需求将剖断一下是否普通话与一行,要是是一行带普通话而且有行间距,此时总体中度应该减去行间距。彰显的Label若是用的是自适应中度,也应该做一下料定,一行中文带行间距时,不安装Label的lineSpace属性。倘令你也超出这么坑,能够因此本小说的德姆o化解,并封装好有的方法,便于今后的应用。

标签:

内容摘要

  • UILabel展现多行文本
  • UILabel设置行间距
  • 缓和单行文本 & 多行文本突显的主题素材

二、文本获取中度的艺术:
常常总计文本的中度使用以下三种艺术,通过计算出来的莫大总计父控件的总中度。

技术分享

场地描述

  • 人所共知,UILabel彰显多行的话,私下认可行间距为0,但实际支付中,假使显示多行文本,一般情形下会有分明的行间距。如若想动态调度行间距,则须求赋值富文本属性(而不是文本属性

由此UILabel sizeThatFits获取文本的高度
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0,
100, 1)];
label.font = [UIFont systemFontOfSize:14]; label.numberOfLines = 0;
label.attributedText = attributeString;
CGSize size = [label sizeThatFits:CGSizeMake(label.frame.size.width,
CGFLOAT_MAX)];
NSLog(@”size:%@”, NSStringFromCGSize(size));
NSLog(@”label.frame.size:%@”, NSStringFromCGSize(label.frame.size));
boundingWithRect
NSString *text = @”恰同学少年,风度翩翩”;
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];
三、汉语富文本有行间距的坑:
算算文字中度的坑:
上述三种计算情势在总括包蕴中文,何况有行间距的富文本时,会冒出在企图一行时,文本高度不对,多了二个行间距的惊人。但在总计纯西班牙语时却不会存在这几个状态。那样会导致在存在父控件时,父控件完整中度计算不对。

初步看到这种字号和颜料不等同的字符串,想出个讨巧的格局正是“¥150”多少个UILable,“元/位”三个UILable。前天翻看以前的工程,command点进UIText菲尔德中看出[attributedText]那几个首要字,以前都没在意过UITextField还会有那几个本性,其实UITextView、UILable也许有其一个性,iOS6就已经有了,说来惭愧,对此罚站1分钟。

标题深入分析

Paste_Image.png
给Label设置文本的坑:
在给Label设置富文本时,假若是单排並且带中文,何况安装了区间lineSpace,结果多开掘展现出来多了叁个间距的高度。

NSAttributedString叫做富文本,是一种含有属性的字符串,通过它能够轻便的在叁个字符串中显示出三种字体、字号、字体大小等各差异的风骨,还是能对段落进行格式化。

Label展现多行文本

  • label暗许情形下,只会展现单行文本,主即便因为它的numberOfLines属性值是1;如若要展现多行,把这几个属性值改成0即可。

self.lblResult.numberOfLines = 0;
  • 暗许情状下,会展现成那样:
Label设置行间距\_多行0间距.png
  • 借使想增多行间距,你可能会这么做:

    • 写贰个string转变到AttributedString的方法(也许给字符串扩大三个分拣)

    -(NSAttributedString *)getAttributedStringWithString:(NSString *)string lineSpace:(CGFloat)lineSpace {
        NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:string];
        NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
        paragraphStyle.lineSpacing = lineSpace; // 调整行间距
        NSRange range = NSMakeRange(0, [string length]);
        [attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:range];
        return attributedString;
    

}
* 赋值富文本属性 objc
NSString string =
@”家弦户诵,UILabel展现多行的话,暗中认可行间距为0,但事实上成本中,假如展现多行文本,一般境况下会有自然的行间距。如果想动态调解行间距,则供给赋值富文本属性
*(实际不是文本属性)”;
// 5:行间距
self.lblResult.attributedText = [self
getAttributedStringWithString:string lineSpace:5];
“`

  • 结果如下图:
Label设置行间距\_多行5间距.png



=============== 华丽的分割线 ===============  
</br>

标题:以上办法呈现多创作本貌似没有格外态,但若是文本独有一行呢?

Paste_Image.png
四、施工方案:
计算文字高度的坑:
看清行数与是或不是留存中文,当行数为一行,而且存在汉语时,需求将总括结果的莫斯科大学减去行间距。此时才为不易文本精确中度。
给Label设置文本的坑:
急需剖断是还是不是超越一行,当先一行不设置富文本的lineSpace。
//文本的中度减去字体中度小于等于行间距,剖断为近些日子独有1行
if ((rect.size.height – _font.lineHeight) <=
paragraphStyle.lineSpacing){
if ([self containChinese:str]) { //固然包蕴中文
rect = CGRectMake(rect.origin.x, rect.origin.y, rect.size.width,
rect.size.height-paragraphStyle.lineSpacing);
}
}

透过以下代码就可以兑现地点图示效果,十一分有利,从此再也不用设置五个UILable,况且处心积虑的管理它们的长度了。

Label呈现单行文本

  • 体现单行粤语:

NSString *string = @"文本只有一行会显示什么样?";
self.lblResult.attributedText = [self getAttributedStringWithString:string lineSpace:5];

Label设置行间距_单行中文5间距.png

  • 来得单行克罗地亚共和国(Republic of Croatia)语:

NSString *string = @"good good study day day up";
self.lblResult.attributedText = [self getAttributedStringWithString:string lineSpace:5];

Label设置行间距_单行立陶宛(Lithuania)语5间距1.png

  • 透过相比较开采,用平等的方式,单行展现中文 &
    土耳其共和国(Türkiye Cumhuriyeti)语,效果分歧,普通话会多了部分单手!心中立马有种蛋蛋的悲伤,一丝丝凄凉……

//剖断若是带有中文

1    UILabel * aLable = [[UILabel alloc]
initWithFrame:CGRectMake(100, 500, 200, 40)];

遇到标题今后

  • 查询API-NSMutableParagraphStyle

// Indent:缩进
@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
    
  • (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;
    }

2    aLable.textAlignment = NSTextAlignmentCenter;

品味化解难点

  • 重构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; // 调整行间距
    NSRange range = NSMakeRange(0, [string length]);
    [attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:range];
    // 设置文本偏移量
    [attributedString addAttribute:NSBaselineOffsetAttributeName value:@(baselineOffset) range:range];
    return attributedString;
}
  • 于是乎单行文本显示成那样:
Label设置行间距\_单行中文5间距偏移量.png



Label设置行间距\_单行英文5间距偏移量.png
  • 那么多行呢?
Label设置行间距\_多行中文5间距偏移量.png



Label设置行间距\_多行英文5间距偏移量.png



我擦!

Paste_Image.png
五、封装与利用(便于现在的选择)
对NSString进行以下办法的加码。

3    [self.view addSubview:aLable];

标题深入分析

  • 经过上面的言传身教剖析,能够简单的拿走结论:
    • 未设置行间距和偏移量,什么难点都并未有,只是行与行之间展现得比较紧促!
    • 只设置行间距,多行和单行朝鲜语情形下,展现没不日常,但单行中文突显会有标题,尾巴部分会有空白!
    • 既设置行间距,也安装偏移的场地下,单行呈现没不寻常,但多行彰显有标题!

/**

4

消除办法

  • 多市价况下,不安装偏移!
  • 总括文字高度,能够管理总括带行间距的
    */

5    NSString * aString = @”¥150 元/位”;

那便是说难题来了,如何判别label显示几行吧?

  • 小编用相比较笨的秘技:总结某多少个牢固字符的万丈,然后再计算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; // 调整行间距
NSDictionary *attrs = @{
                            NSFontAttributeName : self.lblResult.font,
                            NSParagraphStyleAttributeName : paragraphStyle
                            };
// 计算一行文本的高度
CGFloat oneHeight = [@"测试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,那样一般化解了下边包车型大巴主题素材,但细心的您估摸会开掘叁个标题:CGFloat offset = -(1.0/3 * lineSpace) - 1.0/3;那行代码是怎样意思?

6

关于 f(x) = -(1.0/3 * x) – 1.0/3

  • offset是透过穷举法归咎总结出来的,可能相当不够规范,但在类型中用起来蛮好。
  • 基于文件内容,描点

// 描点
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);
    // 关联layer和贝塞尔路径
    self.linesLayer.path = linePath;
    CGPathRelease(linePath);
    // 创建Animation
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
    animation.fromValue = @(0.0);
    animation.toValue = @(1.0);
    self.linesLayer.autoreverses = NO;
    animation.duration = 1.5f;
    // 设置layer的animation
    [self.linesLayer addAnimation:animation forKey:nil];
    self.linesLayer.strokeEnd = 1;
}
![Uploading Label设置行间距_归纳总结offset的算法_323780.png . . .]

Label设置行间距_综上所述总计offset的算法.png

  • (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];

7    //富文本对象

// NSLog(@”size:%@”, NSStringFromCGSize(rect.size));

8    NSMutableAttributedString * aAttributedString =
[[NSMutableAttributedString alloc] initWithString:aString];

//文本的高度减去字体高度小于等于行间距,判断为当前只有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;

9

}

10    //富文本样式

//判别借使含有汉语

11    [aAttributedString addAttribute:NSForegroundColorAttributeName 
//文字颜色

  • (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;
    }
    /
    *

12                              value:[UIColor redColor]

13                              range:NSMakeRange(0, 4)];

  • 计量最大行数文字中度,能够拍卖计算带行间距的
    */

14

15    [aAttributedString addAttribute:NSFontAttributeName           
//文字字体

  • (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;
    }
    }
    /**

16                              value:[UIFont systemFontOfSize:25]

17                              range:NSMakeRange(0, 4)];

  • 算算是不是超过一行 用于给Label 赋值attribute text的时候
    当先一行设置lineSpace
    */

18

19    aLable.attributedText = aAttributedString;

  • (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;
    }
    }

常用属性:

NSFontAttributeName           文字字体

NSParagraphStyleAttributeName     段落样式(字符串通过“\n”实行分层,此设置必需在lable.numberOfLines
= 0时有效,value通过NSMutableParagraphStyle设置,它有以下属性)

[段落样式-插曲]

1 @property(readwrite) CGFloat
lineSpacing;              //行间距

2 @property(readwrite) CGFloat
paragraphSpacing;           //段间距

3 @property(readwrite) NSTextAlignment alignment;          
//对齐方式

4 @property(readwrite) CGFloat firstLineHeadIndent;         
//首行缩紧

5 @property(readwrite) CGFloat headIndent;              
//除首行之外别的行缩进

6 @property(readwrite) CGFloat tailIndent;              
//每行容纳字符的上升的幅度

7 @property(readwrite) NSLineBreakMode lineBreakMode;        
//换市场价格势

8 @property(readwrite) CGFloat minimumLineHeight;          
//最小行高

9 @property(readwrite) CGFloat maximumLineHeight;          
//最大行高

10 @property(readwrite) NSWritingDirection
baseWritingDirection;  //书写情势(NSWritingDirectionNatural,NSWritingDirectionLeftToRight,NSWritingDirectionRightToLeft)

11 @property(readwrite) CGFloat lineHeightMultiple;

12 @property(readwrite) CGFloat paragraphSpacingBefore;

13 @property(readwrite) float hyphenationFactor;

14 @property(readwrite,copy,NS_NONATOMIC_IOSONLY) NSArray *tabStops
NS_AVAILABLE_IOS(7_0);

15 @property(readwrite,NS_NONATOMIC_IOSONLY) CGFloat
defaultTabInterval NS_AVAILABLE_IOS(7_0);

[段落样式demo]

1    UILabel * lable = [[UILabel alloc] initWithFrame:CGRectMake(50,
100, self.view.frame.size.width-100, 200)];

2    lable.backgroundColor = [UIColor lightGrayColor];

3    lable.numberOfLines = 0;

4    [self.view addSubview:lable];

5

6    NSString * string = @”Always believe that something wonderful is
about \nto happen!”;

7

8    //富文本

9    NSMutableAttributedString * attributedString =
[[NSMutableAttributedString alloc] initWithString:string];

10

11    //段落样式

12    NSMutableParagraphStyle * paragraphStyle =
[[NSMutableParagraphStyle alloc] init];

13

14 #warning  lable.numberOfLines必得为0,段落样式才生效

15    //行间距

16    paragraphStyle.lineSpacing = 10.0;

17    //段落间距

18    paragraphStyle.paragraphSpacing = 20.0;

19

20 //    paragraphStyle.baseWritingDirection =
NSWritingDirectionLeftToRight;

21 //    paragraphStyle.firstLineHeadIndent = 10.0;

22 //    paragraphStyle.headIndent = 50.0;

23 //    paragraphStyle.tailIndent = 200.0;

24

25    [attributedString addAttribute:NSParagraphStyleAttributeName

26                              value:paragraphStyle

27                              range:NSMakeRange(0, string.length)];

28

29    lable.attributedText = attributedString;

相关文章