[这是第四篇]
导语:在iOS中,有时候显示文本,需要设置文本的行间距、指定显示行数、如果文本内容超出显示行数,省略结尾部分的内容以……方式省略。这些都可以使用UILabel来是实现,前提是你扩展了UILabel这方面的特性。
——2017年4月14日
新增的特性
之前已经写过这部分内容,但是代码不简洁,使用不太方便,现在重新表述一下,思路是一样的
1、可以设置文本的显示行数。文本内容超出显示行数,结尾部分的内容以……方式省略,文本内容不超出显示行数,默认显示全部文本。
2、可以设置行间距。
一 、代码实现
1-1、新增NSString 的Size分类定义,用来计算文本占据的size#####
// NSString+Size.h
@interface NSString (Size)
/**
根据字体、行数、行间距和constrainedWidth计算文本占据的size
@param font 字体
@param numberOfLines 显示文本行数,值为0不限制行数
@param lineSpacing 行间距
@param constrainedWidth 文本受限的宽度
@param isLimitedToLines 记录文本是否被numberOfLines限制
@return 返回文本占据的size
*/
- (CGSize)textSizeWithFont:(UIFont*)font
numberOfLines:(NSInteger)numberOfLines
lineSpacing:(CGFloat)lineSpacing
constrainedWidth:(CGFloat)constrainedWidth
isLimitedToLines:(BOOL *)isLimitedToLines;
@end
- 将文本size的计算放到NSString的分类中,是合情合理的,之前放到UILabel的分类中,这点不太好。
- isLimitedToLines是用来记录文本是否被numberOfLines限制,在业务中是为了控制文本的展开和收起(后面有Demo)。
1-2、NSString+Size的重要实现
- (CGSize)textSizeWithFont:(UIFont*)font
numberOfLines:(NSInteger)numberOfLines
lineSpacing:(CGFloat)lineSpacing
constrainedWidth:(CGFloat)constrainedWidth
isLimitedToLines:(BOOL *)isLimitedToLines{
if (self.length == 0) {
return CGSizeZero;
}
CGFloat oneLineHeight = font.lineHeight;
CGSize textSize = [self boundingRectWithSize:CGSizeMake(constrainedWidth, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:font} context:nil].size;
CGFloat rows = textSize.height / oneLineHeight;
CGFloat realHeight = oneLineHeight;
// 0 不限制行数
if (numberOfLines == 0) {
if (rows >= 1) {
realHeight = (rows * oneLineHeight) + (rows - 1) * lineSpacing;
}
}else{
if (rows > numberOfLines) {
rows = numberOfLines;
if (isLimitedToLines) {
*isLimitedToLines = YES; //被限制
}
}
realHeight = (rows * oneLineHeight) + (rows - 1) * lineSpacing;
}
return CGSizeMake(constrainedWidth, realHeight);
}
2-1、新增UILabel 的FitLines分类,让文本适应于指定的行数
// UILabel+FitLines.h
@interface UILabel (FitLines)
/**
最大显示宽度
*/
@property (nonatomic,assign)CGFloat qsConstrainedWidth;
/**
行间距
*/
@property (nonatomic,assign)CGFloat qsLineSpacing;
/**
文本适应于指定的行数
@return 文本是否被numberOfLines限制
*/
- (BOOL)qs_adjustTextToFitLines:(NSInteger)numberOfLines;
@end
- 在初始化UILabel的时候,设置qsConstrainedWidth和qsLineSpacing,然后需要展示UILabel的内容时候,调用qs_adjustTextToFitLines就可以了,相应设置好frame就好了。
2-2、UILabel+FitLines的重要实现
- (BOOL)qs_adjustTextToFitLines:(NSInteger)numberOfLines{
if (!self.text || self.text.length == 0) {
return NO;
}
self.numberOfLines = numberOfLines;
BOOL isLimitedToLines = NO;
CGSize textSize = [self.text textSizeWithFont:self.font numberOfLines:self.numberOfLines lineSpacing:self.qsLineSpacing constrainedWidth:self.qsConstrainedWidth isLimitedToLines:&isLimitedToLines];
//单行的情况
if (fabs(textSize.height - self.font.lineHeight) < 0.00001f) {
self.qsLineSpacing = 0.0f;
}
//设置文字的属性
NSMutableAttributedString * attributedString = [[NSMutableAttributedString alloc] initWithString:self.text];
NSMutableParagraphStyle * paragraphStyle = [[NSMutableParagraphStyle alloc] init];
[paragraphStyle setLineSpacing:self.qsLineSpacing];
paragraphStyle.lineBreakMode = NSLineBreakByTruncatingTail;//结尾部分的内容以……方式省略
[attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [self.text length])];
[attributedString addAttribute:NSForegroundColorAttributeName value:self.textColor range:NSMakeRange(0, [self.text length])];
[attributedString addAttribute:NSFontAttributeName value:self.font range:NSMakeRange(0, [self.text length])];
[self setAttributedText:attributedString];
self.bounds = CGRectMake(0, 0, textSize.width, textSize.height);
return isLimitedToLines;
}
三、使用(初始化和显示文本)
- (UILabel *)contentLabel{
if (!_contentLabel) {
_contentLabel = [[UILabel alloc] init];
_contentLabel.backgroundColor = [UIColor clearColor];
_contentLabel.font = [UIFont systemFontOfSize:QSTextFontSize];
_contentLabel.textColor = [UIColor blackColor];
_contentLabel.qsConstrainedWidth = SCREEN_WIDTH - 30;
_contentLabel.qsLineSpacing = QSTextLineSpacing;
}
return _contentLabel;
}
- (void)layoutSubviewsWithModel:(QSShowTextCellModel *)model{
//...
_contentLabel.text = model.content;
BOOL isLimitedToLines = [_contentLabel qs_adjustTextToFitLines:model.contentLines];
_contentLabel.frame = CGRectMake(15, CGRectGetMaxY(self.titleLabel.frame) + 10,
CGRectGetWidth( _contentLabel.bounds),CGRectGetHeight(_contentLabel.bounds));
// ...
}
- 其他代码见Demo
四、UILabel扩展特性的使用
- 这个Demo是使用UITableView组织文本的显示。每一个cell可以显示title和content,cell中先指定content文本显示3行,行间距是5.0f
- 如果content文本用3行不能全部显示,文本下面出现“显示文本”按钮,点击“显示全文”按钮,可以展开全部文本,此时按钮变成“收起全文”;点击按钮可以收起全文,依旧显示3行,按钮恢复成“显示全文”。
- 如果content文本用3行可以全部显示,不会出现按钮。
- content显示的文本可以设置行数值,行间距值,收起全文和展开全文都是利用UILabel的扩展特性来实现的。
- demo中使用cellModel保存cell中content显示的行数-- contentLines,通过contentlines来预先计算cell的高度。具体参见Demo源码。
** 效果图如下**
源码直通车:QSUseLabelDemo
如果可以解决您的问题,请star一下哈