UILabel算是iOS里使用最多的控件了吧,下面来说说它特殊的应用需求吧
一、设置字间距、行间距
这是一个比较常见的需求了
写一个UILabel的分类
@interface UILabel (extension)
/**
* 设置字间距
*/
-(void)setColumnSpace:(CGFloat)columnSpace;
/**
* 设置行距
*/
- (void)setRowSpace:(CGFloat)rowSpace;
@end
#import "UILabel+extension.h"
#import <CoreText/CoreText.h>
@implementation UILabel (extension)
- (void)setColumnSpace:(CGFloat)columnSpace
{
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithAttributedString:self.attributedText];
//调整间距
[attributedString addAttribute:(__bridge NSString *)kCTKernAttributeName value:@(columnSpace) range:NSMakeRange(0, [attributedString length])];
self.attributedText = attributedString;
}
- (void)setRowSpace:(CGFloat)rowSpace
{
self.numberOfLines = 0;
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithAttributedString:self.attributedText];
//调整行距
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineSpacing = rowSpace;
paragraphStyle.baseWritingDirection = NSWritingDirectionLeftToRight;
[attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [self.text length])];
self.attributedText = attributedString;
}
@end
然后再重写UILabel
@interface RDNewLabel : UILabel
@property (nonatomic, assign) float charactSpace; //字间距
@property (nonatomic, assign) float lineSpace; //行间距
+ (CGFloat)textHeight:(NSString *)text width:(CGFloat)labelWidth font:(UIFont *)font charactSpace:(CGFloat)charactSpace LineSpace:(CGFloat)lineSpace numberLines:(NSInteger)numberLines;
(CGFloat)textWidth:(NSString *)text height:(CGFloat)labelHeight font:(UIFont *)font charactSpace:(CGFloat)charactSpace LineSpace:(CGFloat)lineSpace;
#define CharactSpacing 0.4 //字间距
#define LinesSpacing 4.0 //行间距
@implementation RDNewLabel
- (void)setText:(NSString *)text{
[super setText:text];
//默认字间距为0.4
if (_charactSpace==0) {
[self setColumnSpace:CharactSpacing];
}else{
[self setColumnSpace:_charactSpace];
}
//默认行间距为4.0,当设置0.01时则不设置行间距
if (_lineSpace == 0) {
[self setRowSpace:LinesSpacing];
}else{
if (_lineSpace <= 0.01) {
}else{
[self setRowSpace:_lineSpace];
}
}
}
+ (CGFloat)textHeight:(NSString *)text width:(CGFloat)labelWidth font:(UIFont *)font charactSpace:(CGFloat)charactSpace LineSpace:(CGFloat)lineSpace numberLines:(NSInteger)numberLines{
CGFloat textHeight = 0;
RDNewLabel *label = [RDNewLabel new];
label.font = font;
if (charactSpace == 0) {
charactSpace = CharactSpacing;
}
label.charactSpace = charactSpace;
if (lineSpace == 0) {
lineSpace = LinesSpacing;
}
label.lineSpace = lineSpace;
label.text = text;
label.numberOfLines = numberLines;
textHeight = [label sizeThatFits:CGSizeMake(labelWidth, MAXFLOAT)].height;
return textHeight;
}
+ (CGFloat)textWidth:(NSString *)text height:(CGFloat)labelHeight font:(UIFont *)font charactSpace:(CGFloat)charactSpace LineSpace:(CGFloat)lineSpace{
CGFloat textWidth = 0;
RDNewLabel *label = [RDNewLabel new];
label.font = font;
if (charactSpace == 0) {
charactSpace = CharactSpacing;
}
label.charactSpace = charactSpace;
if (lineSpace == 0) {
lineSpace = LinesSpacing;
}
label.lineSpace = lineSpace;
label.text = text;
label.numberOfLines = 0;
textWidth = [label sizeThatFits:CGSizeMake(MAXFLOAT, labelHeight)].width;
return textWidth;
}
二、Label 两端对齐
很多情况我们会遇到这样的需求,要求Label文字两端对齐。
使用UILabel的NSTextAlignment设置两端对齐并不是达到效果,而使用UILabel的attributedText确实可以实现两端对齐。
重写UILabel的setText方法
@implementation ALLabel
- (void)setText:(NSString *)text{
NSMutableAttributedString *attributedStr = [[NSMutableAttributedString alloc]initWithString:text];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc]init];
paragraphStyle.alignment = NSTextAlignmentJustified;//设置两端对齐
[attributedStr setAttributes:@{NSParagraphStyleAttributeName:paragraphStyle,NSFontAttributeName:self.font,NSUnderlineStyleAttributeName:[NSNumber numberWithInteger:NSUnderlineStyleNone]} range:NSMakeRange(0, attributedStr.length)];
[self setAttributedText:attributedStr];
}
初始化一个ALLabel
@property (weak, nonatomic) IBOutlet ALLabel *label;
NSString* msg = @"壬戌之秋,七月既望,苏子与客泛舟游于赤壁之下。清风《赤壁赋》文徵明书徐来,水波不兴。举酒属(zhǔ)客,诵明月之诗,歌窈窕之章。少(shǎo) 焉,月出于东山之上,徘徊于斗(dǒu)牛之间。白露横江,水光接天。纵一苇之所如,凌万顷之茫然。浩浩乎如冯 (píng) 虚御风,而不知其所止;飘飘乎如遗世独立,羽化而登仙。”
_label.text = msg;
计算label自适应高度还是一样
CGSize resultSize = [msg boundingRectWithSize:size options:NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesFontLeading | NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: [UIFont systemFontOfSize:fontSize]} context:nil].size
三、分行显示
也许我们会遇到类似需求:本来多行的文字,却首先只显示两行,最二行末尾处放置一个“查看更多”的按钮,点击查看更多按钮则全部显示。
思路:
1、设置一个lines为0的allTextLabel;
2、放置一个lines为1的firstLineLabel,top、left、right和allTextLabel对齐;
3、放置一个lines也为1的secondLineLabel,left与firstLineLabel对齐,top与firstLineLabel的bottom间距为0,right与“查看更多按钮”的间距为0;
4、放置一个“查看更多”的按钮moreTextButton,right与firstLineLabel对齐,top与firstLineLabel的bottom间距为0,宽度固定
@property (weak, nonatomic) IBOutlet UILabel *allTextLabel;
@property (weak, nonatomic) IBOutlet UILabel *firstLineLabel;
@property (weak, nonatomic) IBOutlet UILabel *secondLineLabel;
@property (weak, nonatomic) IBOutlet UIButton *moreTextButton;
根据文字内容和宽度返回一个以行数line为索引的数组
#import <CoreText/CoreText.h>
- (NSArray *)getSeparatedLinesFromLabelText:(NSString *)text font:(UIFont *)font width:(CGFloat)width
{
CTFontRef myFont = CTFontCreateWithName((__bridge CFStringRef)([font fontName]), [font pointSize], NULL);
NSMutableAttributedString *attStr = [[NSMutableAttributedString alloc] initWithString:text];
[attStr addAttribute:(NSString *)kCTFontAttributeName value:(__bridge id)myFont range:NSMakeRange(0, attStr.length)];
CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attStr);
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, CGRectMake(0,0,width,MAXFLOAT));
CTFrameRef frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, 0), path, NULL);
NSArray *lines = (__bridge NSArray *)CTFrameGetLines(frame);
NSMutableArray *linesArray = [[NSMutableArray alloc]init];
for (id line in lines)
{
CTLineRef lineRef = (__bridge CTLineRef )line;
CFRange lineRange = CTLineGetStringRange(lineRef);
NSRange range = NSMakeRange(lineRange.location, lineRange.length);
NSString *lineString = [text substringWithRange:range];
[linesArray addObject:lineString];
}
return linesArray;
}
接下来就是赋值了
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
NSString * msg = @"土地是以它的肥沃和收获而被估价的;才能也是土地,不过它生产的不是粮食,而是真理。如果只能滋生瞑想和幻想的话,即使再大的才能也只是砂地或盐池,那上面连小草也长不出来的
_allTextLabel.hidden = TRUE;
CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width;
_textLines = [self getSeparatedLinesFromLabelText:msg font:[UIFont systemFontOfSize:15] width:screenWidth-90];
_firstLineLabel.text = _textLines[0];
_secondLineLabel.text = _textLines[1];
}
点击查看更多按钮,其实就是赋值后隐藏firstLineLabel和secondLineLabel
- (IBAction)onClickShowMoreText:(id)sender {
_allTextLabel.text = msg ;
_allTextLabel.hidden = FALSE;
_firstLineLabel.hidden = TRUE;
_secondLineLabel.hidden = TRUE;
_moreTextButton.hidden = TRUE;
}