网络知识 娱乐 ios 文字自适应,随文字增多,高度变化

ios 文字自适应,随文字增多,高度变化

前言:我们在做开发时,有时候lable的文字多少,并不是我们确定的,这个时候就需要lable的大小随文字的变化而变化。一般都是宽度固定,让高度发生变化。下面介绍几种方法,和其中有可能出现的问题。
注意:使用文字自适应的方法:首先设置frame大小,在赋值文字,最后在自适应,顺序不要写错,不然可能自适应无效。原理:自适应是根据文字多少来变化的,如果不先赋值文字,默认就是0个文字,高度自然不会变化

1:使用lable的 sizeToFit方法,

sizeToFit会自动根据文字的多少来改变宽度和高度,需要注意的是:在初始化lable时,需要先设置frame大小。然后赋值text。虽然sizeToFit会最终改变lable的宽度和高度,但不会改变lable的居左和居上的大小,即frame里的X,Y的参数。而且lable的宽度改变的很小。比如你设的lable的宽度是300,sizeToFit以后宽度会变280(这个只是估算,具体以实际大小为准。)相当于高度的变化,宽度就变得小了。如果你不设置lable的宽度,sizeToFit后宽度就随机的,具体看下面的示例:

 UILabel *testLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 100, 50, 20)];
   testLabel.text = @"weIU让我以任务女包女包n二次不能不能传:n1.的我我以为要问问嗯嗯非常丰富股份。n2.问问无诶无诶无诶无诶weuwieuwieuwieuwieuwie任务和维护 问问偶尔";
   testLabel.font = [UIFont systemFontOfSize:14];
   //   testLabel.textAlignment=NSTextAlignmentCenter;
   testLabel.numberOfLines = 0;
   [testLabel sizeToFit];
   testLabel.textColor=[UIColor blackColor];
   testLabel.backgroundColor=[UIColor yellowColor];
   [self.view addSubview:testLabel];

sizeToFit是用范围很广,即使设置lable行距间距等等属性,也是可以正常展示的。

2:使用sizeThatFits方法

sizeThatFits和sizeToFit都可以实现文字自适应。区别在于sizeToFit会自动改变lable的大小,但sizeThatFits不会改变lable的size大小,这个只是计算出最优的 size 大小,如果想lable大小改变,需要重新赋值frame。

 UILabel *testLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 100, 300, 20)];
   testLabel.text = @"weIU让我以任务女包女包n二次不能不能传:n1.的我我以为要问问嗯嗯非常丰富股份。n2.问问无诶无诶无诶无诶weuwieuwieuwieuwieuwie任务和维护 问问偶尔";
   testLabel.font = [UIFont systemFontOfSize:14];
   //   testLabel.textAlignment=NSTextAlignmentCenter;
   testLabel.numberOfLines = 0;
   
   //使用sizeThatFit计算lable大小
   CGSize sizeThatFit = [testLabel sizeThatFits:CGSizeMake(200, 200)];
   testLabel.frame    = CGRectMake(testLabel.frame.origin.x, testLabel.frame.origin.y, sizeThatFit.width, sizeThatFit.height);
   
   testLabel.textColor=[UIColor blackColor];
   testLabel.backgroundColor=[UIColor yellowColor];
   [self.view addSubview:testLabel];

注意:重新设置frame是最好以计算出来的size来赋值(这样的话,sizeThatFits后面的参数宽度和最终lable展示的宽度就相差不大的。但这个宽度不能超出屏幕外,否则超出屏幕外的文字会看不见的)。高度可以随便写,lable的高度最终是以文字的多少而定的。使用sizeThatFits方法时,在初始化lable的时候可以不用写frame的,可以在sizeThatFits方法后面重新赋值frame(我这里初始化的时候赋值了frame,所以重新赋值的时候,x,y的值我直接取了之前的testLabel.frame.origin.x和testLabel.frame.origin.y)。

3:使用boundingRectWithSize方法

boundingRectWithSize和sizeThatFits很类似,也是重新计算出size,不过比sizeThatFits多了几个参数。

UILabel *testLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 100, 300, 20)];
   testLabel.text = @"weIU让我以任务女包女包n二次不能不能传:nr1.的我我以为要问问嗯嗯非常丰富股份。nr2.问问无诶无诶无诶无诶weuwieuwieuwieuwieuwie任务和维护 问问偶尔";
   testLabel.font = [UIFont systemFontOfSize:14];
   testLabel.numberOfLines = 0;
   CGSize s = [testLabel.text boundingRectWithSize:CGSizeMake(320, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin  attributes:@{NSFontAttributeName:testLabel.font} context:nil].size;//求文本的大小
   // 并不是高度计算不对,我估计是计算出来的数据是 小数,在应用到布局的时候稍微差一点点就不能保证按照计算时那样排列,所以为了确保布局按照我们计算的数据来,就在原来计算的基础上 取ceil值,再加1;
   CGFloat height = ceil(s.height) + 1;
   testLabel.frame    = CGRectMake(testLabel.frame.origin.x, testLabel.frame.origin.y, s.width, height);
   
   testLabel.textColor=[UIColor blackColor];
   testLabel.backgroundColor=[UIColor yellowColor];
   [self.view addSubview:testLabel];

在使用boundingRectWithSize计算高度时,有时候不准确,需要注意一下几点

  1. 有部分说文字里带有rn这些转义字符,导致不准确。我自己实验下,如果boundingRectWithSize方法里的参数attributes只设置了字体大小(这个字体大小一定取lable的字体大小,如果2个不一样也会计算错误),这些转义字符不影响的
  2. boundingRectWithSize里的参数size里的宽度你设置后,最后lable的宽度也取得这个值,但实际上lable的宽度比这个值要小一些,但不影响整体布局,如果影响了,你们可以通过打印看看宽度最终是多少,适当修改size的宽度的大小。size的高度尽量写大些,如果你的文字高度大于你写的这个高度,文字也会以你写的高度来布局,并不会自动增加高度。
  3. 有部分人说,不准确可以修改boundingRectWithSize里的options这个参数,设置为NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading,但swift好像不能这么写的。
  4. 在boundingRectWithSize方法里的参数attributes里我不仅设置了字体,还设置了行距,首位缩进,字体间距等等。这样计算的高度总是少了一行(这个问题是我写的遇到的,不知道是真的有问题,还是我计算错误,暂时还没解决,如果有知道原因的,欢迎下方评论)

关于boundingRectWithSize计算高度不准确的解决方法

使用前2个方法来适配文字。
使用UITextView代替lable。使用方法如下:

 UITextView *ysTextView = [[UITextView alloc] initWithFrame:CGRectMake(20, 100, 300, 10)];
   ysTextView.text = @"我原以为的以为,那些苍老的画面rn都终将会老去,走吧rn走吧rn我的血和汗rn
rn某天,我听你说着rn看遍千山万水rn开心的如此忘杯"
; // 可以将标签 ,进行转换 // NSString*ysStr =[ysTextView.text stringByReplacingOccurrencesOfString:@"
" withString:@"rn"];
ysTextView.font = [UIFont systemFontOfSize:14]; ysTextView.backgroundColor = [UIColor orangeColor]; ysTextView.textContainerInset = UIEdgeInsetsZero; ysTextView.textContainer.lineFragmentPadding = 0; ysTextView.scrollEnabled = NO;//当文字超过视图的边框时是否允许滑动,默认为"YES" ysTextView.editable = NO;//是否允许编辑内容,默认为"YES" [self.view addSubview:ysTextView]; CGFloat height=[(NSString *)ysTextView.text boundingRectWithSize:CGSizeMake(ysTextView.frame.size.width,CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:ysTextView.font} context:nil].size.height; CGRect textViewFrame = ysTextView.frame; textViewFrame.size.height = height; ysTextView.frame = textViewFrame;

上面UItextview方法是引用的别人的,详细的在这里 如何处理有换行的字符串,算高度.

4:使用sizeToFit和Masonry自动布局结合使用。

首先使用Masonry是先添加lable到view上,然后在布局frame。由于sizeToFit需要先设置宽度(如果不设置宽度,默认是以整个屏幕的宽度来计算lable高度的)。所以使用Masonry布局时宽度就是固定了(如果你们的宽度不固定,就不要使用此方法)。
示例如下:先写死宽度,然后计算出高度,设置居左为0,居下-20,宽度和高度为lable的宽高

      //定位城市
    UILabel *cityLab = [[UILabel alloc]init];
    cityLab.text = @"万余人业务员入围由入伍颜如玉我从不把VB如无意外有人问";
    //设置宽度
    cityLab.frame = CGRectMake(0, 0, 100, 0);
    //换行
    cityLab.numberOfLines = 0;
    //文字自适应
    [cityLab sizeToFit];
    cityLab.textAlignment = NSTextAlignmentCenter;
    [self.view addSubview:cityLab];
    [cityLab mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.mas_equalTo(0);
        make.bottom.mas_equalTo(-20);
        make.width.mas_equalTo(cityLab.frame.size.width);
        make.height.mas_equalTo(cityLab.frame.size.height);
    }];

如果有什么问题,欢迎下面评论指正。
参考链接:
如何处理有换行的字符串,算高度.
iOS 使用 boundingRectWithSize: 计算 UILabel 高度错误的解决方案
使用boundingRectWithSize计算内容高度的坑