UILabel 是我在第一次上手项目中,用得最多的一个控件。非常多的地方需要用它来显示文本信息。
通常需要绘制它的Frame、设置它的字体、颜色等等。最常见遇到的问题时,该如何去设置文本的大小以及位置,如果美工已经明确给出了视觉效果图,那么对于字体的大小,颜色都可以十分容易的进行设置了。而位置仍然是一个十分头疼的问题。
本文将主要就Text Attributes 和 Layout UILabel 来说一下我的体会。
Accessing the Text Attributes
首先,我们来看一下UILable的常见属性。
objectivec
UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(0, 120, 32]0, 30)]; label.text = @"文本内容文本内容文本内容"; label.attributedText = [[NSAttributedString alloc]initWithString:@"属性文本属性文本"]; label.font = [UIFont systemFontOfSize:15.0f]; label.textColor = [UIColor blackColor]; //文本的在文本框的显示位置 label.textAlignment = NSTextAlignmentLeft; //文字过长时的现实方式 label.lineBreakMode = NSLineBreakByWordWrapping; //文本框是否允许多行(布局相关) label.numberOfLines = 0; //设置是否是高亮 label.highlighted=YES; //高亮颜色 label.highlightedTextColor=[UIColor redColor]; //设置阴影颜色 label.shadowColor=[UIColor blueColor]; //阴影偏移量 label.shadowOffset=CGSizeMake(0.5, 0.5);
其中大多数属性都是非常容易理解的。这里简单提一下其中的几个属性的枚举值。
NSTextAlignment
NSTextAlignmentLeft //左对齐
NSTextAlignmentCenter //居中
NSTextAlignmentRight //右对齐
NSTextAlignmentJustified//最后一行自然对齐
NSTextAlignmentNatural //默认对齐脚本
NSLineBreakMode
NSLineBreakByWordWrapping = 0,//以空格为边界,保留单词
NSLineBreakByCharWrapping, //保留整个字符
NSLineBreakByClipping, //简单剪裁,到边界为止
NSLineBreakByTruncatingHead, //按照"……文字"显示
NSLineBreakByTruncatingTail, //按照"文字……文字"显示
NSLineBreakByTruncatingMiddle //按照"文字……"显示
首先设置UILabel的Frame,然后设置以上属性,我们便可以得到你想要的文本框。
问题来了 每次都这样配置好麻烦啊,有没有默认配置?
这个自然是有的,就比如我只写了frame与text属性,UILabel也会有默认的样式来显示内容。但是在开发中,特别是当没有UI给定我们字体的样式时,如何设计出正常的(不丑)的文本样式呢?那么,就用系统的默认字体吧。
objectivec
UIFont *bodyFont = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
我们将bodyFont设置成了UIFontStyleBody,系统不仅提供了body的字体,还有更多其他的:
objectivec
NSString *const UIFontTextStyleHeadline; NSString *const UIFontTextStyleSubheadline; NSString *const UIFontTextStyleBody; NSString *const UIFontTextStyleFootnote; NSString *const UIFontTextStyleCaption1; NSString *const UIFontTextStyleCaption2;
在不同位置使用不同的默认字体,这样是不是能够省去一些设计的麻烦呢。
当然我们也可以对获取到的默认格式字体,进行修改,下面的代码中,我向UIFontTextStyleBody中追加了加粗效果。
objectivec
UIFontDescriptor *existingDescriptor = [bodyFont fontDescriptor]; UIFontDescriptorSymbolicTraits traints = existingDescriptor.symbolicTraits; traints |= UIFontDescriptorTraitBold; UIFontDescriptor *bodyBoldDescriptor = [existingDescriptor fontDescriptorWithSymbolicTraits:traints]; UIFont *boldBodyFont = [UIFont fontWithDescriptor:bodyBoldDescriptor size:0];
其中使用的UIFontDescriptor类,苹果的官方解释相信非常好理解。
UIFontDescriptor objects provide a mechanism to describe a font with a dictionary of attributes. This font descriptor can be used later to create or modify a UIFont object.
那么通过这个类,我们就可以创建或者改造一个字体对象了。当然可供改造的属性很多,这里就不一一介绍了,因为很多我也没有尝试过。
问题又来了 文本样式就不能丰富一点么?
关于文本框的样式,简单来说,就是文本框可以显示“艺术字”么?UILabel提供了attributedText属性,让我们为UILabel设置Attributed字体。
简单来说,过程是这样的:
objectivec
UILabel *lbl2 = [[UILabel alloc] initWithFrame:CGRectMake(0, 220, 320, 30)]; NSString *str = @"为Label设置属性字符串"; NSDictionary *fontAttributeDic = @{NSFontAttributeName:[UIFont preferredFontForTextStyle:UIFontTextStyleBody], NSForegroundColorAttributeName:[UIColor blueColor], NSStrokeColorAttributeName:[UIColor orangeColor], NSStrokeWidthAttributeName: @(-5), NSUnderlineStyleAttributeName: @(NSUnderlineStyleDouble), NSUnderlineColorAttributeName: [UIColor blackColor]}; NSMutableAttributedString *mutableAttributedStr = [[NSMutableAttributedString alloc]initWithString:str attributes:fontAttributeDic]; lbl2.attributedText = mutableAttributedStr; [self.view addSubview:lbl2];
代码中我们首先做了一个字典,字典中包含了我需要的属性字符串的AttributeName。其中有前景色、边缘色、边缘宽度(设置为-5,就表示边缘在字体内部了)、下划线类型、下划线颜色等等。
Tips:当同时设置了label.text 与 label.attributedText 时,以后设置的为准。
也就是说
objectivec
label.Text = @"aaaaa"; label.attributedText = @"bbbbb" ;
最后显示在界面上的,会是attributedText,反之亦然。
上面代码在模拟器中效果图大概就是这样子的啦:
Layout UILabel
了解了UILable的相关属性之后,真正麻烦的事情就开始了。该如何去写UILabel的CGRectFrame呢?第一次上手iOS写界面,我将所有的UILabel的宽高都写的死死的,起初感觉没什么异常。但当文本长度过长时,就显示不全了。你可能会说显示不全,就把UILabel高度调大,然后让文本可以多行显示,可是高度调大多少呢?10?20?30?……这样子总是瞎蒙显然是不行的。毕竟在真正开发中,文本信息基本都是从服务器获取的,必然是不定长的,那么就让我们来看看如何在文本不定长的情况下来写UILabel的Frame。
当然,使用约束是一种更加方便的方法。但是初入门时,写Frame也是不可避免的。
就像下面的真实开发中,标题 地址信息是要求必须显示完全的。这样的情况下,使用固定值来写Frame就不合适了。
UILabel固定宽度与高度的情况下
写一个固定宽高的UILabel,设置高度远大于文本高度时,文本在文本框中是垂直方向上居中显示的。
objectivec
UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(10, 20, 300, 100)]; label.backgroundColor = [UIColor yellowColor]; label.font = [UIFont systemFontOfSize:17.0f]; label.text = @"当高度过高时,UILabel是居中显示的!!!"; [self.view addSubview:label]; UILabel *label2 = [[UILabel alloc]initWithFrame:CGRectMake(10, 220, 300, 100)]; label2.backgroundColor = [UIColor yellowColor]; label2.font = [UIFont systemFontOfSize:17.0f]; label2.text = @"当高度过高时,UILabel是居中显示的!!!并且设置了多行显示"; label2.numberOfLines = 0; [self.view addSubview:label2];
UILabel 没有提供垂直方向上的居中显示,如果你想要文本每次都在文本框的左上角位置,那么需要自己实现了。
文本框垂直方向居中
也正是因为这个原因,当我们调整UILabel的高度时,发现文本的位置也发生了上下偏移。
但通常开发中,我们希望可以控制文本在Y方向上的位置,那么高度就显得非常重要了。
情况二:通过文本内容与字体,计算文本的所需宽高!!!!!!!!!!!
iOS提供了通过文本的字体及内容,计算文本框所需宽高的方法。返回的CGSize是紧紧包围着文本内容的。
这样,我们就再也不需要去估计UILabel的宽高了,可以通过下面的方法,来根据内容和字体写文本框宽高。
具体是下面这样的:
objectivec
UILabel *label3 = [[UILabel alloc]init]; label3.backgroundColor = [UIColor yellowColor]; label3.font = [UIFont systemFontOfSize:17.0f]; label3.text = @"根据文本框内容及字体,计算所需宽高"; label3.numberOfLines = 0; //================================================================================================================== NSDictionary *attributeDic = @{NSFontAttributeName: [UIFont systemFontOfSize:17.0f]}; CGSize constraintSize = CGSizeMake(100, CGFLOAT_MAX); CGSize realSize = [label3.text boundingRectWithSize:constraintSize options:NSStringDrawingTruncatesLastVisibleLine|NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:attributeDic context:nil].size; [label3 setFrame:CGRectMake(10, 310, realSize.width, realSize.height)]; //================================================================================================================== [self.view addSubview:label3];
上面的代码中,我们使用了下面的这个方法。
- (CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options attributes:(NSDictionary *)attributes context:(NSStringDrawingContext *)context
此方法可以返回,符合条件的bounding rect,也就是我们需要的CGRect对象,其中也就有我们需要的宽和高了。
而此方法中传入的两个值非常关键,一个是size,还有一个是attributes。这两个参数前一个指明了文本框最宽最高值可以是多少,可以理解为这是一个约束框,当计算出来的宽高小于此size时,计算结果就是realSize,当计算结果大于约束宽高时,realSize以约束宽高为准,有了约束宽高,就不用担心文本非常非常长的情况下,文本框也变得巨大无比。总之,返回的CGRect中的宽高是在约束size内的。
另一个参数attributes,是一个字典,反映了字体的属性。我们需要自己构造这个字典。NSFontAttributeName等等字段,在上面的文章中也有提及,这里就不再重复了。需要注意的是,在NSFontAttributeName 的Value,[UIFont systemFontOfSize:17.0f]获取到的UIFont,这个字典中的获取方法需要与你之前配置UILabel.font的设置方法一致,否则有可能计算出的高度,与实际的高度不符!!!我就被这问题坑过,不同的UIFont获取方法,计算出来的结果会有几个像素的偏差!!!!
好了,让我们来看一下效果,配置了约束Size,宽度为100,高度不限。
CGSize constraintSize = CGSizeMake(100, CGFLOAT_MAX);
显示效果会是下面这样的。通过此方法,我们可以轻松的控制UILabel的Frame了!!!
可以看一下效果图。右上方红框内的Frame的H,就是我们在约束了W为100的情况下,计算出来的W和H了!~
当然了这个方法,还有一个姐妹方法,不过已经过期了,还是建议大家用这个方法来计算宽高。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。