您的位置:首页 > 产品设计 > UI/UE

完美解决 向UILable 文字最后插入N张图片,支持向限制行数的UILable 最后一行插入,多余文字显示...

2016-04-01 10:32 656 查看
效果:





====直接上代码吧===

//
//  UILabel+StringFrame.h
//  QYER
//
//  Created by qyer on 15/3/19.
//  Copyright (c) 2015年 QYER. All rights reserved.
//

#import <UIKit/UIKit.h>

/**
*  uilable 行间距高度
*/
static CGFloat const lineSapceHeight = 5.0f;

@interface UILabel (StringFrame)

#pragma mark - 获取UILable Size

- (CGSize)boundingRectWithSize:(CGSize)size;
/**
*  根据文字长度计算大小
*
*  @param content 文字长度
*  @param pFont   文字字号
*  @param pWidth  宽度
*
*/
+(CGSize)getContentSize:(NSString *)content font:(UIFont *)pFont width:(CGFloat)pWidth;
/**
*  根据文字长度计算大小
*
*  @param content 文字长度
*  @param pFont   文字字号
*  @param pHeight  高度
*
*/
+(CGSize)getContentSize:(NSString *)content font:(UIFont *)pFont height:(CGFloat)pHeight;
/**
*  根据文本获取size ,有最大 宽高限制
*
*  @param string    文本
*  @param maxWidth  最大宽
*  @param maxHeight 最大高
*  @param font      字体
*  @param lineSpace 行间距(如果使用默认的,就传nil)
*
*  @return size
*/
+(CGSize)getContentSizeWithContentText:(NSString *)string andMaxWidth:(CGFloat)maxWidth andMaxHeight:(CGFloat)maxHeight AndFont:(UIFont*)font andLineSpacing:(NSNumber *)lineSpace;
/**
*  根据文本获取size ,有最大 宽高限制
*
*  @param string    文本
*  @param maxWidth  最大宽
*  @param maxHeight 最大高
*  @param attribute 富文本属性
*
*  @return size
*/
+(CGSize)getContentSizeWithContentText:(NSString *)string andMaxWidth:(CGFloat)maxWidth andMaxHeight:(CGFloat)maxHeight andAttributes:(NSDictionary *)attribute;

#pragma mark - 获取UILable 每行显示的文字

/**
*  获取lalbe 每行文字
*
*  @return 每行文字数组
*/
- (NSArray *)getSeparatedLines;
/**
*  获取lalbe 每行文字
*
*  @param text 根据文字内容
*
*  @return 每行文字数组
*/
- (NSArray *)getSeparatedLinesWithText:(NSString*)text;
/**
*  获取lalbe 每行文字
*
*  @param content 文字内容
*  @param fonte   fonte description
*  @param size    size description
*
*  @return return value description
*/
+(NSArray *)getSeparatedLinesWithText:(NSString*)content andFonte:(UIFont *)fonte andSize:(CGSize)size;

#pragma mark - 完美解决 向UILable 文字最后插入N张图片,支持向限制行数的UILable 最后一行插入,多余文字显示...

/**
*  向文字末尾追加图片,适用于已知Size的UILable
*
*  @param contentStr 文字内容
*  @param imgs       插入的图片数组, 图片最好带间隔哦
*/
-(void)insertImgToContentLast:(NSString *)contentStr imgs:(NSArray *)imgs;
/**
*  向文字末尾追加图片,适用于AutoLayout 的UILable
*
*  @param contentStr    文字内容
*  @param imgs          插入的图片数组, 图片最好带间隔哦
*  @param estimateWidth 预估的UILable 最大宽度(已知的最大宽度)
*/
-(void)insertImgToContentLast:(NSString *)contentStr imgs:(NSArray *)imgs estimateWidth:(CGFloat)estimateWidth;
/**
*  向已知文字后插入图片
*
*  @param insertImgArr           insertImgArr description
*  @param appendAttributedString 可为nil
*/
-(void)configTitleLableAttributedString:(NSArray *)insertImgArr AttributedString:(NSMutableAttributedString *)appendAttributedString;

@end


//
//  UILabel+StringFrame.m
//  QYER
//
//  Created by qyer on 15/3/19.
//  Copyright (c) 2015年 QYER. All rights reserved.
//

#import "UILabel+StringFrame.h"

#import <CoreText/CoreText.h>

@implementation UILabel (StringFrame)

#pragma mark - 获取UILable Size

- (CGSize)boundingRectWithSize:(CGSize)size
{
NSDictionary *attribute = @{NSFontAttributeName: self.font};

CGSize retSize = [self.text boundingRectWithSize:size
options:\
NSStringDrawingTruncatesLastVisibleLine |
NSStringDrawingUsesLineFragmentOrigin |
NSStringDrawingUsesFontLeading
attributes:attribute
context:nil].size;

return retSize;
}

+(CGSize)getContentSize:(NSString *)content font:(UIFont *)pFont width:(CGFloat)pWidth{

CGSize contentSize;
if (ios7) {
contentSize = [content boundingRectWithSize:CGSizeMake(pWidth, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:[NSDictionary dictionaryWithObjectsAndKeys:pFont,NSFontAttributeName, nil] context:nil].size;
}else{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
contentSize = [content sizeWithFont:pFont constrainedToSize:CGSizeMake(pWidth, MAXFLOAT) lineBreakMode:NSLineBreakByCharWrapping];
#pragma clang diagnostic pop

}
return contentSize;
}

+(CGSize)getContentSize:(NSString *)content font:(UIFont *)pFont height:(CGFloat)pHeight{

CGSize contentSize;
if (ios7) {
contentSize = [content boundingRectWithSize:CGSizeMake(MAXFLOAT, pHeight) options:NSStringDrawingUsesLineFragmentOrigin attributes:[NSDictionary dictionaryWithObjectsAndKeys:pFont,NSFontAttributeName, nil] context:nil].size;
}else{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
contentSize = [content sizeWithFont:pFont constrainedToSize:CGSizeMake(MAXFLOAT, pHeight) lineBreakMode:NSLineBreakByCharWrapping];
#pragma clang diagnostic pop

}
return contentSize;
}

/**
*  根据文本获取size ,有最大 宽高限制
*
*  @param string    文本
*  @param maxWidth  最大宽
*  @param maxHeight 最大高
*  @param attribute 富文本属性
*
*  @return size
*/
+(CGSize)getContentSizeWithContentText:(NSString *)string andMaxWidth:(CGFloat)maxWidth andMaxHeight:(CGFloat)maxHeight  andAttributes:(NSDictionary *)attribute{
CGSize size = CGSizeZero;
if (IsEmpty(string)) {
return size;
}
if (string) {
if ([string respondsToSelector:
@selector(boundingRectWithSize:options:attributes:context:)]) {
size = [string boundingRectWithSize:CGSizeMake(maxWidth, maxHeight)
options:NSStringDrawingUsesLineFragmentOrigin| NSStringDrawingTruncatesLastVisibleLine |NSStringDrawingUsesFontLeading
attributes:attribute
context:nil].size;
}else {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
size = [string sizeWithFont:attribute[@"NSFontAttributeName"]
constrainedToSize:CGSizeMake(maxWidth, maxHeight)
lineBreakMode:NSLineBreakByCharWrapping];
#pragma clang diagnostic pop
}
}
if (!CGSizeEqualToSize(CGSizeZero, size)) {

CGFloat wight = maxWidth;
CGFloat height = ceil(size.height);
/**
*  使用 NIAttributedLabel 有个bug ,当文字只有一行或不满一行 会出现文字显示不出来
*/
if (!attribute) {
NSArray *rows = [UILabel getSeparatedLinesWithText:string  andFonte:attribute[NSFontAttributeName] andSize:size];
if ([rows count]==1) {
CGSize offsetSize = [UILabel getContentSize:string font:attribute[NSFontAttributeName] width:maxWidth];
size = CGSizeMake(ceil(offsetSize.width) , ceil(offsetSize.height));
}else{
size = CGSizeMake(wight ,height);
}
}else {
size = CGSizeMake(wight ,height);
}
}
return size;
}

/**
*  根据文本获取size ,有最大 宽高限制
*
*  @param string    文本
*  @param maxWidth  最大宽
*  @param maxHeight 最大高
*  @param font      字体
*  @param lineSpace 行间距(如果使用默认的,就传nil)
*
*  @return size
*/
+(CGSize)getContentSizeWithContentText:(NSString *)string andMaxWidth:(CGFloat)maxWidth andMaxHeight:(CGFloat)maxHeight AndFont:(UIFont*)font andLineSpacing:(NSNumber *)lineSpace{
CGSize size = CGSizeZero;
if (IsEmpty(string)) {
return size;
}
if (string && font) {
if ([string respondsToSelector:
@selector(boundingRectWithSize:options:attributes:context:)]) {
NSMutableParagraphStyle * paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;
paragraphStyle.alignment = NSTextAlignmentLeft;
if (lineSpace) {
paragraphStyle.lineSpacing = [lineSpace floatValue];
}
size = [string boundingRectWithSize:CGSizeMake(maxWidth, maxHeight)
options:NSStringDrawingUsesLineFragmentOrigin| NSStringDrawingTruncatesLastVisibleLine |NSStringDrawingUsesFontLeading
attributes:@{NSFontAttributeName:font,
NSParagraphStyleAttributeName:paragraphStyle}
context:nil].size;

}else {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
size = [string sizeWithFont:font
constrainedToSize:CGSizeMake(maxWidth, maxHeight)
lineBreakMode:NSLineBreakByCharWrapping];
#pragma clang diagnostic pop
}
}
if (!CGSizeEqualToSize(CGSizeZero, size)) {

CGFloat wight = ceil(maxWidth);
CGFloat height = ceil(size.height );

/**
*  使用 NIAttributedLabel 有个bug ,当文字只有一行或不满一行 会出现文字显示不出来
*/
NSArray *rows = [UILabel getSeparatedLinesWithText:string  andFonte:font andSize:size];
if ([rows count]==1) {
CGSize offsetSize = [UILabel getContentSize:string font:font width:maxWidth];
size = CGSizeMake(ceil(offsetSize.width) , ceil(offsetSize.height));
}else{
size = CGSizeMake(wight ,height);
}

}
return size;
}

#pragma mark - 获取UILable 每行显示的文字

/**
*  获取lalbe 每行文字
*
*  @return 每行文字数组
*/
- (NSArray *)getSeparatedLines {
return [self getSeparatedLinesWithText:self.text];
}

/**
*  获取lalbe 每行文字
*
*  @param text 根据文字内容
*
*  @return 每行文字数组
*/
- (NSArray *)getSeparatedLinesWithText:(NSString*)text
{
/**
*  fix NSConcreteMutableAttributedString initWithString:: nil value
*/
if (!(text && [text isKindOfClass:[NSString class]])) {
return nil;
}

return [UILabel getSeparatedLinesWithText:text andFonte:[self font] andSize:[self frame].size];
}

/**
*  获取lalbe 每行文字
*
*  @param content 文字内容
*  @param fonte   fonte description
*  @param size    size description
*
*  @return 每行文字数组
*/
+(NSArray *)getSeparatedLinesWithText:(NSString*)content andFonte:(UIFont *)fonte andSize:(CGSize)size{
if (!(content&&[content isKindOfClass:[NSString class]]) ||
!(fonte&& [fonte isKindOfClass:[UIFont class]]) ||
CGSizeEqualToSize(CGSizeZero, size)) {
return nil;
}
NSString *text = content;
UIFont   *font = fonte;
CGRect    rect = CGRectMake(0, 0, size.width,size.height);

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,rect.size.width,100000));

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];
}

CFRelease(frameSetter);
CFRelease(myFont);
CFRelease(frame);
CFRelease(path);

return (NSArray *)linesArray;
}

#pragma mark - 完美解决 向UILable 文字最后插入N张图片,支持向限制行数的UILable 最后一行插入,多余文字显示...

/**
*  向文字末尾追加图片,适用于已知Size的UILable
*
*  @param contentStr 文字内容
*  @param imgs       插入的图片数组, 图片最好带间隔哦
*/
-(void)insertImgToContentLast:(NSString *)contentStr imgs:(NSArray *)imgs{
if (IsEmpty(contentStr) || !imgs || [imgs count] == 0) {
self.text = IsEmpty(contentStr)?@"":contentStr;
return ;
}

[self insertImgToContentLast:contentStr imgs:imgs estimateWidth:[self frame].size.width];
}
/**
*  向文字末尾追加图片,适用于AutoLayout 的UILable
*
*  @param contentStr    文字内容
*  @param imgs          插入的图片数组, 图片最好带间隔哦
*  @param estimateWidth 预估的UILable 最大宽度(已知的最大宽度)
*/
-(void)insertImgToContentLast:(NSString *)contentStr imgs:(NSArray *)imgs estimateWidth:(CGFloat)estimateWidth{
if (IsEmpty(contentStr) || !imgs || [imgs count] == 0 || estimateWidth == 0) {
self.text = IsEmpty(contentStr)?@"":contentStr;
return ;
}

//获取每行文字需要预设宽度,不然每个字都会是单独的一行
self.width = estimateWidth;
NSArray *textLineArr =  [self getSeparatedLinesWithText:contentStr];
NSInteger maxLine = self.numberOfLines;

if (maxLine ==  0) {
self.text = contentStr;
//追加图片
[self configTitleLableAttributedString:imgs AttributedString:nil];
return;
}
NSInteger lastLineIndex = maxLine - 1;

if ([textLineArr count] <= lastLineIndex) {
self.text = contentStr;
//追加图片
[self configTitleLableAttributedString:imgs AttributedString:nil];
return;
}

__block CGFloat imgWith = 0.0;
[imgs enumerateObjectsUsingBlock:^(UIImage* img, NSUInteger idx, BOOL * _Nonnull stop) {
imgWith += img.size.width;
}];

CGFloat lastTextMaxWith = estimateWidth - imgWith;
if (lastTextMaxWith <= 0) {
self.text = contentStr;
//追加图片
[self configTitleLableAttributedString:imgs AttributedString:nil];
return ;
}

if ([textLineArr count] > lastLineIndex) {
NSMutableString *muShowTitle = [NSMutableString string];
[textLineArr enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if (idx > (lastLineIndex - 1)) {
//预设宽度
self.width = lastTextMaxWith;
//最大宽带下能显示的字数
NSArray *lastLineArr = [self getSeparatedLinesWithText:textLineArr[lastLineIndex]];
NSString *lastLineText = lastLineArr[0];
//                DDLogDebug(@"====lastLineText=======%@==",lastLineText);
if ([lastLineArr count] > 1) {
lastLineText = [lastLineText stringByReplacingCharactersInRange:NSMakeRange(lastLineText.length - 3, 3) withString:@"..."];
}
//                DDLogDebug(@"====lastLineArr[0]=======%@==",lastLineText);
[muShowTitle appendString:lastLineText];

* stop = YES;
return ;
}
[muShowTitle appendString:textLineArr[idx]];
}];
self.text = muShowTitle;
//        self.width = estimateWidth;
}

//追加图片
[self configTitleLableAttributedString:imgs AttributedString:nil];
}

/**
*  向已知文字后插入图片
*
*  @param insertImgArr           insertImgArr description
*  @param appendAttributedString 可为nil
*/
-(void)configTitleLableAttributedString:(NSArray *)insertImgArr AttributedString:(NSMutableAttributedString *)appendAttributedString{
if (!insertImgArr || [insertImgArr count] == 0) {
return ;
}
if (!appendAttributedString) {
appendAttributedString = [[NSMutableAttributedString alloc] initWithString:self.text];
}

[insertImgArr enumerateObjectsUsingBlock:^(UIImage* img, NSUInteger idx, BOOL * _Nonnull stop) {

NSTextAttachment *textAttachment = [[NSTextAttachment alloc] init];
//带 x 的
textAttachment.image = img;

CGFloat mid = self.font.descender + self.font.capHeight;
CGFloat imgY = self.font.descender - textAttachment.image.size.height/2 + mid + 2;
textAttachment.bounds = CGRectMake(0, imgY, textAttachment.image.size.width, textAttachment.image.size.height);

NSAttributedString *iconAttributedString = [NSAttributedString attributedStringWithAttachment:textAttachment];
[appendAttributedString replaceCharactersInRange:NSMakeRange(self.text.length, 0) withAttributedString:iconAttributedString];
/**
fix,当文字刚好够一行,添加图片后折行,but.第二行图片和第一行文字没有行间距。。 http://scottzhu.com/blog/2015/02/14/attach-stars-to-the-end-of-a-uilabel/ */
[appendAttributedString appendAttributedString: [[NSAttributedString alloc] initWithString:@" "]];

}];

self.attributedText = appendAttributedString;
}

@end
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: