前言:我们在做开发时,有时候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二次不能不能传:\n\r1.的我我以为要问问嗯嗯非常丰富股份。\n\r2.问问无诶无诶无诶无诶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计算高度时,有时候不准确,需要注意一下几点
有部分说文字里带有\r\n这些转义字符,导致不准确。我自己实验下,如果boundingRectWithSize方法里的参数attributes只设置了字体大小(这个字体大小一定取lable的字体大小,如果2个不一样也会计算错误),这些转义字符不影响的boundingRectWithSize里的参数size里的宽度你设置后,最后lable的宽度也取得这个值,但实际上lable的宽度比这个值要小一些,但不影响整体布局,如果影响了,你们可以通过打印看看宽度最终是多少,适当修改size的宽度的大小。size的高度尽量写大些,如果你的文字高度大于你写的这个高度,文字也会以你写的高度来布局,并不会自动增加高度。有部分人说,不准确可以修改boundingRectWithSize里的options这个参数,设置为NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading,但swift好像不能这么写的。在boundingRectWithSize方法里的参数attributes里我不仅设置了字体,还设置了行距,首位缩进,字体间距等等。这样计算的高度总是少了一行(这个问题是我写的遇到的,不知道是真的有问题,还是我计算错误,暂时还没解决,如果有知道原因的,欢迎下方评论)
关于boundingRectWithSize计算高度不准确的解决方法
<1> 使用前2个方法来适配文字。
<2> 使用UITextView代替lable。使用方法如下:
UITextView *ysTextView = [[UITextView alloc] initWithFrame:CGRectMake(20, 100, 300, 10)];ysTextView.text = @"我原以为的以为,那些苍老的画面\r\n都终将会老去,走吧\r\n走吧\r\n我的血和汗\r\n<br />\r\n某天,我听你说着\r\n看遍千山万水\r\n开心的如此忘杯";// 可以将标签 ,进行转换// NSString*ysStr =[ysTextView.text stringByReplacingOccurrencesOfString:@"<br />" withString:@"\r\n"];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计算内容高度的坑