zoukankan      html  css  js  c++  java
  • 完美解决 向UILable 文字最后插入N张图片,支持向限制行数的UILable 最后一行插入,多余文字显示...

    效果:

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

    //
    //  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 (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 (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] 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 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
  • 相关阅读:
    LeetCode 623. Add One Row to Tree
    LeetCode 894. All Possible Full Binary Trees
    LeetCode 988. Smallest String Starting From Leaf
    LeetCode 979. Distribute Coins in Binary Tree
    LeetCode 814. Binary Tree Pruning
    LeetCode 951. Flip Equivalent Binary Trees
    LeetCode 426. Convert Binary Search Tree to Sorted Doubly Linked List
    LeetCode 889. Construct Binary Tree from Preorder and Postorder Traversal
    LeetCode 687. Longest Univalue Path
    LeetCode 428. Serialize and Deserialize N-ary Tree
  • 原文地址:https://www.cnblogs.com/DamonTang/p/5344048.html
Copyright © 2011-2022 走看看