UILabel封装——生成富文本,计算文本高度,图文混排
2016-03-14 本文已影响2641人
Wang66
更新
(2016.08.09)在最近的项目开发中碰到了像下图这样文本中混合图标的情况,如果分为UILabel和UIImageView两个控件来写,本身就比较繁琐,而且要考虑若文本较长时图标是要换行显示,即UIImageView要更新布局。今天有时间,利用TextKit
的NSTextAttachment
将图片作为富文本的附件植入富文本,并且写了一个UILable
的分类进行了封装。当然也完全可以不写成分类的形式,直接封装入YWLabel
也是可以的。
YWLabel
项目中富文本的展示非常普遍,若通过UILable的接口方法去设置是非常繁琐麻烦的,另外,文本动态高度计算的问题也很常见,因此有必要对UILabel进行封装。以便我们处理这两个问题,下面这个YWLabel主要就针对这两个问题进行了封装,给开发提供方便,提高效率。
// YWLabel.h
#import <UIKit/UIKit.h>
@interface YWLabel : UILabel
- (void)labelText:(NSString *)text
lineSpacing:(CGFloat)l_spacing;
- (void)labelText:(NSString *)text
sectionSpacing:(CGFloat)s_spacing
lineSpacing:(CGFloat)l_spacing;
+ (NSAttributedString *)attributedTextArray:(NSArray *)texts
textColors:(NSArray *)colors
textfonts:(NSArray *)fonts;
+ (NSAttributedString *)attributedTextArray:(NSArray *)texts
textColors:(NSArray *)colors
textfonts:(NSArray *)fonts
lineSpacing:(CGFloat)l_spacing;
+ (CGSize)sizeLabelWidth:(CGFloat)width
attributedText:(NSAttributedString *)attributted;
+ (CGSize)sizeLabelWidth:(CGFloat)width
text:(NSString *)text
font:(UIFont *)font;
+ (CGSize)sizeLabelWidth:(CGFloat)width
text:(NSString *)text
font:(UIFont *)font
lineSpacing:(CGFloat)l_spacing;
@end
// YWLabel.m
#import "YWLabel.h"
@implementation YWLabel
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if(self)
{
self.backgroundColor = [UIColor whiteColor];
}
return self;
}
- (void)labelText:(NSString *)text
lineSpacing:(CGFloat)l_spacing
{
if(l_spacing<0){
self.text = text;
return;
}
self.numberOfLines = 0;
NSMutableAttributedString *attributedStr = [[NSMutableAttributedString alloc] initWithString:text];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineSpacing = l_spacing;
[attributedStr addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, text.length)];
[attributedStr addAttribute:NSForegroundColorAttributeName value:self.textColor range:NSMakeRange(0, text.length)];
[attributedStr addAttribute:NSFontAttributeName value:self.font range:NSMakeRange(0, text.length)];
self.attributedText = attributedStr;
}
- (void)labelText:(NSString *)text
sectionSpacing:(CGFloat)s_spacing
lineSpacing:(CGFloat)l_spacing
{
if(s_spacing<=0 && l_spacing<=0){
self.text = text;
return;
}
self.numberOfLines = 0;
NSMutableAttributedString *attributedStr = [[NSMutableAttributedString alloc] initWithString:text];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineSpacing = l_spacing; // lineSpacing
paragraphStyle.paragraphSpacing = s_spacing; // paragraphSpacing
[attributedStr addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, text.length)];
[attributedStr addAttribute:NSForegroundColorAttributeName value:self.textColor range:NSMakeRange(0, text.length)];
[attributedStr addAttribute:NSFontAttributeName value:self.font range:NSMakeRange(0, text.length)];
self.attributedText = attributedStr;
}
+ (NSAttributedString *)attributedTextArray:(NSArray *)texts
textColors:(NSArray *)colors
textfonts:(NSArray *)fonts
{
if(texts.count == 0){
return nil;
}
NSMutableAttributedString *resultAttributedStr = [[NSMutableAttributedString alloc] init];
for(int i=0; i<texts.count; i++)
{
NSString *text = texts[i];
NSMutableAttributedString *mAttributedStr = [[NSMutableAttributedString alloc] initWithString:text];
[mAttributedStr addAttribute:NSForegroundColorAttributeName value:colors[i] range:NSMakeRange(0, text.length)];
[mAttributedStr addAttribute:NSFontAttributeName value:fonts[i] range:NSMakeRange(0, text.length)];
[resultAttributedStr appendAttributedString:mAttributedStr];
}
return resultAttributedStr;
}
+ (NSAttributedString *)attributedTextArray:(NSArray *)texts
textColors:(NSArray *)colors
textfonts:(NSArray *)fonts
lineSpacing:(CGFloat)l_spacing
{
if(texts.count == 0){
return nil;
}
NSMutableAttributedString *resultAttributedStr = [[NSMutableAttributedString alloc] init];
for(int i=0; i<texts.count; i++)
{
NSString *text = texts[i];
NSMutableAttributedString *mAttributedStr = [[NSMutableAttributedString alloc] initWithString:text];
[mAttributedStr addAttribute:NSForegroundColorAttributeName value:colors[i] range:NSMakeRange(0, text.length)];
[mAttributedStr addAttribute:NSFontAttributeName value:fonts[i] range:NSMakeRange(0, text.length)];
[resultAttributedStr appendAttributedString:mAttributedStr];
}
if(l_spacing>0){
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineSpacing = l_spacing;
[resultAttributedStr addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, resultAttributedStr.length)];
}
return resultAttributedStr;
}
+ (CGSize)sizeLabelWidth:(CGFloat)width
attributedText:(NSAttributedString *)attributted
{
if(width<=0){
return CGSizeZero;
}
UILabel *lab = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, width, 1000)];
lab.attributedText = attributted;
lab.numberOfLines = 0;
CGSize labSize = [lab sizeThatFits:lab.bounds.size];
return labSize;
}
+ (CGSize)sizeLabelWidth:(CGFloat)width
text:(NSString *)text
font:(UIFont *)font
{
if(width<=0 || text.length == 0){
return CGSizeZero;
}
UILabel *lab = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, width, 1000)];
lab.text = text;
if(font){
lab.font = font;
}
CGSize labSize = [lab sizeThatFits:lab.bounds.size];
return labSize;
}
+ (CGSize)sizeLabelWidth:(CGFloat)width
text:(NSString *)text
font:(UIFont *)font
lineSpacing:(CGFloat)l_spacing
{
if(width<=0 || text.length == 0){
return CGSizeZero;
}
if(l_spacing<=0){
UILabel *lab = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, width, 1000)];
lab.text = text;
lab.numberOfLines = 0;
if(font){
lab.font = font;
}
CGSize labSize = [lab sizeThatFits:lab.bounds.size];
return labSize;
}
else
{
UILabel *lab = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, width, 1000)];
lab.numberOfLines = 0;
if(font){
lab.font = font;
}
NSMutableAttributedString *mAttriStr = [[NSMutableAttributedString alloc] initWithString:text];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineSpacing = l_spacing;
[mAttriStr addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, text.length)];
lab.attributedText = mAttriStr;
CGSize labSize = [lab sizeThatFits:lab.bounds.size];
return labSize;
}
}
@end
上面就是我们封装的YWLabel,下面我们来测试一下:
// ViewController.m
#import "ViewController.h"
#import "YWLabel.h"
#define Lab_W self.view.bounds.size.width-30.f
#define FONT(X) [UIFont systemFontOfSize:X]
#define BFONT(X) [UIFont boldSystemFontOfSize:X]
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor lightGrayColor];
NSArray *textsArray = @[@"你呀别总想搞个大新闻!",
@"图样图森破!",
@"什么大风大浪我没见过",
@"我和华莱士谈笑风生"];
NSArray *colorsArray = @[[UIColor orangeColor],
[UIColor redColor],
[UIColor blueColor],
[UIColor greenColor]];
NSArray *fontsArray = @[FONT(20), BFONT(35), FONT(25), BFONT(30)];
YWLabel *lab = [[YWLabel alloc] initWithFrame:CGRectMake(15.f, 80.f, Lab_W, 10)];
lab.numberOfLines = 0;
// 生成富文本字符串
NSAttributedString *attributeStr = [YWLabel attributedTextArray:textsArray
textColors:colorsArray
textfonts:fontsArray
lineSpacing:20.f];
lab.attributedText = attributeStr;
// 计算富文本的高度
CGFloat lab_h = [YWLabel sizeLabelWidth:Lab_W
attributedText:attributeStr].height;
lab.frame = CGRectMake(15.f, 80.f, Lab_W, lab_h);
[self.view addSubview:lab];
}
@end
效果图:
屏幕快照 2016-03-14 20.44.44.pngUILabel+ImageTextFix
——UILabel+ImageTextFix.h——
#import <UIKit/UIKit.h>
@interface UILabel (ImageTextFix)
// 由多个attributedString拼接成新的attributedString,item意为由text或image生成的单个attributedString
+ (NSAttributedString *)fixAttributeStrWithItems:(NSArray *)items;
//
+ (NSAttributedString *)fixAttributedStrWithTexts:(NSArray *)texts
textColors:(NSArray *)colors
textfonts:(NSArray *)fonts
image:(UIImage *)image
insertIndex:(NSInteger)index
lineSpacing:(CGFloat)l_spacing;
+ (NSAttributedString *)fixAttributedStrWithTexts:(NSArray *)texts
textColors:(NSArray *)colors
textfonts:(NSArray *)fonts
image:(UIImage *)image
insertIndex:(NSInteger)index
imageBounds:(CGRect)bounds
lineSpacing:(CGFloat)l_spacing;
// 由text生成attributedString
+ (NSAttributedString *)attributedStrWithText:(NSString *)text textColor:(UIColor *)color textFont:(UIFont *)font;
// 由image生成attributedString
+ (NSAttributedString *)attributedStrWithImage:(UIImage *)image imageBounds:(CGRect)bounds;
@end
——UILabel+ImageTextFix.m——
#import "UILabel+ImageTextFix.h"
@implementation UILabel (ImageTextFix)
// 由多个attributedString拼接成新的attributedString,item意为由text或image生成的单个attributedString
+ (NSAttributedString *)fixAttributeStrWithItems:(NSArray *)items
{
NSMutableAttributedString *resultMAttrStr = [[NSMutableAttributedString alloc] init];
for(int i=0; i<items.count; i++)
{
if([items[i] isKindOfClass:[NSAttributedString class]]){
[resultMAttrStr appendAttributedString:items[i]];
}
}
return resultMAttrStr;
}
// 图文混合,只有一张图片
+ (NSAttributedString *)fixAttributedStrWithTexts:(NSArray *)texts
textColors:(NSArray *)colors
textfonts:(NSArray *)fonts
image:(UIImage *)image
insertIndex:(NSInteger)index
lineSpacing:(CGFloat)l_spacing
{
return [[self class] fixAttributedStrWithTexts:texts
textColors:colors
textfonts:fonts
image:image
insertIndex:index
imageBounds:CGRectZero
lineSpacing:l_spacing];
}
// 同上,多了一个l_spacing参数
+ (NSAttributedString *)fixAttributedStrWithTexts:(NSArray *)texts
textColors:(NSArray *)colors
textfonts:(NSArray *)fonts
image:(UIImage *)image
insertIndex:(NSInteger)index
imageBounds:(CGRect)bounds
lineSpacing:(CGFloat)l_spacing
{
if(texts.count==0){
return nil;
}
NSMutableAttributedString *resultAttrStr = [[NSMutableAttributedString alloc] init];
NSInteger locationIndex = 0;
for(int i=0; i<texts.count; i++)
{
NSString *text = texts[i];
NSAttributedString *tempMAttrStr = [[self class] attributedStrWithText:texts[i] textColor:colors[i] textFont:fonts[i]];
[resultAttrStr appendAttributedString:tempMAttrStr];
// 计算图片应该插入的位置
if(index<=texts.count){
if(index == 0){
locationIndex = 0;
}
else{
if(i<index){
locationIndex+=text.length;
}
}
}
}
if(l_spacing>0){
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineSpacing = l_spacing;
[resultAttrStr addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, resultAttrStr.length)];
}
// 插入图片附件(插入图片要在最后,不然会有影响)
NSMutableAttributedString *resultAttrStr1 = [[self class] insertMAttrStr:resultAttrStr image:image imageBounds:bounds insertIndex:locationIndex];
return resultAttrStr1;
}
+ (NSMutableAttributedString *)insertMAttrStr:(NSMutableAttributedString *)mAttrStr image:(UIImage *)image imageBounds:(CGRect)bounds insertIndex:(NSInteger)index
{
if(image){
NSTextAttachment *attachment = [[NSTextAttachment alloc] init];
attachment.image = image;
attachment.bounds = CGRectMake(bounds.origin.x, bounds.origin.y, bounds.size.width, bounds.size.height);
NSAttributedString *attachmentAttrStr = [NSAttributedString attributedStringWithAttachment:attachment];
[mAttrStr insertAttributedString:attachmentAttrStr atIndex:index];
}
return [mAttrStr copy];
}
// 由text生成attributedString
+ (NSAttributedString *)attributedStrWithText:(NSString *)text textColor:(UIColor *)color textFont:(UIFont *)font
{
NSMutableAttributedString *mAttrStr = [[NSMutableAttributedString alloc] initWithString:text];
[mAttrStr addAttribute:NSForegroundColorAttributeName value:color range:NSMakeRange(0, text.length)];
[mAttrStr addAttribute:NSFontAttributeName value:font range:NSMakeRange(0, text.length)];
return mAttrStr;
}
// 由image生成attributedString
+ (NSAttributedString *)attributedStrWithImage:(UIImage *)image imageBounds:(CGRect)bounds
{
NSTextAttachment *attachment = [[NSTextAttachment alloc] init];
attachment.image = image;
attachment.bounds = CGRectMake(bounds.origin.x, bounds.origin.y, bounds.size.width, bounds.size.height);
NSAttributedString *attachmentAttrStr = [NSAttributedString attributedStringWithAttachment:attachment];
return attachmentAttrStr;
}
@end
——使用——
方式1:
// 数据初始化
UIImage *icon = [UIImage imageNamed:@"biaoji-dacuxiao"];
NSArray *texts = @[@"大起飞精品钢琴课程 ",@"买买买!!!",@"1200元 "];
NSArray *colors = @[[UIColor lightGrayColor],[UIColor orangeColor],[UIColor redColor]];
NSArray *fonts = @[[UIFont systemFontOfSize:15],[UIFont systemFontOfSize:15],[UIFont systemFontOfSize:25]];
UILabel *lab = [[UILabel alloc] initWithFrame:CGRectMake(15.f, 550.f, self.view.bounds.size.width-30.f, 80.f)];
[self.view addSubview:lab];
lab.numberOfLines = 0;
// ----1----图文混合,只有一张图片
lab.attributedText = [UILabel fixAttributedStrWithTexts:texts
textColors:colors
textfonts:fonts
image:icon
insertIndex:3
imageBounds:CGRectMake(0, 5.f, icon.size.width, icon.size.height)
lineSpacing:5.f];
style1.png
方式2:
UILabel *lab = [[UILabel alloc] initWithFrame:CGRectMake(15.f, 550.f, self.view.bounds.size.width-30.f, 80.f)];
[self.view addSubview:lab];
lab.numberOfLines = 0;
// ----2----由多个attributedString拼接成新的attributedString
NSAttributedString *attrStr1 = [UILabel attributedStrWithText:@"大中华精品钢琴课程 " textColor:[UIColor lightGrayColor] textFont:[UIFont systemFontOfSize:15]];
NSAttributedString *attrStr2 = [UILabel attributedStrWithImage:icon imageBounds:CGRectMake(0, 5.f, icon.size.width, icon.size.height)];
NSAttributedString *attrStr3 = [UILabel attributedStrWithText:@"1200元 " textColor:[UIColor redColor] textFont:[UIFont systemFontOfSize:25]];
NSAttributedString *attrStr4 = [UILabel attributedStrWithText:@"买买买" textColor:[UIColor orangeColor] textFont:[UIFont systemFontOfSize:15]];
NSAttributedString *attrStr5 = [UILabel attributedStrWithImage:icon imageBounds:CGRectMake(0, -15.f, icon.size.width, icon.size.height)];
NSAttributedString *resultAttrStr = [UILabel fixAttributeStrWithItems:@[attrStr1,attrStr2,attrStr3,attrStr4,attrStr5]];
lab.attributedText = resultAttrStr;
style2.png
注:
NSTextAttachment
的bounds
属性,应该是用于指定图片附件的位置及尺寸的,但是图片的x坐标指定试了好多次始终是无效的。若文本和图片之间需要间距,上面代码目前是通过空格的本办法实现的。如果有朋友知道怎么指定图片附件的位置,可以告诉我,谢谢。