search

Home  >  Q&A  >  body text

objective-c - ios 超过一定行数的label强制在末尾加上一个...展开且可以点击成全文

如题

比如

这个UIlabel 本该显示成

顶顶顶顶顶顶顶顶顶顶的大多数是是是是
顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶
谁谁谁水水水水是是是是是是是是是是撒
大多数是山东省撒打算打算打算打算的收
水电费第三方第三方说的发送到发送到范
水电费第三方士大夫士大夫。

但是 现在业务要求最多显示3行 如果小于3行有多少航显示多少行 超过三行的话显示如下

顶顶顶顶顶顶顶顶顶顶的大多数是是是是
顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶
谁谁谁水水水水是是是是是是是...展开

其中展开是蓝色 一点击...展开才变成

顶顶顶顶顶顶顶顶顶顶的大多数是是是是
顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶
谁谁谁水水水水是是是是是是是是是是撒
大多数是山东省撒打算打算打算打算的收
水电费第三方第三方说的发送到发送到范
水电费第三方士大夫士大夫。

我现在虽然到达了效果 但是方法比较复杂 且有时候还有问题 我想想问问大家 有没有什么好办法 好思路 最好有代码可以参考 谢谢了

天蓬老师天蓬老师2808 days ago1260

reply all(4)I'll reply

  • 天蓬老师

    天蓬老师2017-04-17 17:34:19

    The limit on the number of characters upstairs is not practical. Chinese characters have the same width, but the width of other characters is inconsistent, such as 1 and 8, one and 1, i and u, W and I...
    This question needs to be used CoreText, manually change the typesetting. There is this kind of AttributeLabel on the Internet. First download the code and take a look. It is difficult to write it completely by hand. Let me give you a look at the code that we downloaded online before the project and modified it by ourselves. It is a bit similar to your needs. He This is just added... For reference, the following method is the method of customizing label

    - (void)drawTextInRect:(CGRect)rect
    {
        CGContextRef context = UIGraphicsGetCurrentContext();
        CGContextSaveGState(context);
        //将当前context的坐标系进行flip,否则上下颠倒
        CGAffineTransform flipVertical = CGAffineTransformMake(1,0,0,-1,0,self.bounds.size.height);
        CGContextConcatCTM(context, flipVertical);
        //设置字形变换矩阵为CGAffineTransformIdentity,也就是说每一个字形都不做图形变换
        CGContextSetTextMatrix(context, CGAffineTransformIdentity);
        NSString *attrStr = self.resultAttributedString.string;
        NSRange range = NSMakeRange(0, attrStr.length);
        NSDictionary *dic = [self.resultAttributedString attributesAtIndex:0 effectiveRange:&range];
        NSMutableParagraphStyle *ps =  [dic objectForKey:NSParagraphStyleAttributeName];
        BOOL truncatTail = NO;
        if(ps.lineBreakMode == NSLineBreakByTruncatingTail)
        {
            truncatTail = YES;
        }
        
        CTFramesetterRef framesetter = [self framesetter];
        CGMutablePathRef pathRef = CGPathCreateMutable();
        CGPathAddRect(pathRef,NULL , CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height));
         _textFrame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), pathRef,NULL );
        NSInteger numberOfLines = [self numberOfDisplayedLines];
        
        CGSize tempSize = self.frame.size;
        CGSize trueSize = [self getLLLLabelSize];
       
        if (_textFrame)
        {
            if (numberOfLines > 0 && tempSize.height < trueSize.height)
            {
                CFArrayRef lines = CTFrameGetLines(_textFrame);
                
                CGPoint lineOrigins[numberOfLines];
                CTFrameGetLineOrigins(_textFrame, CFRangeMake(0, numberOfLines), lineOrigins);
                NSAttributedString *attributedString = self.resultAttributedString;
                for (CFIndex lineIndex = 0; lineIndex < numberOfLines; lineIndex++)
                {
                    CGPoint lineOrigin = lineOrigins[lineIndex];
                    CGContextSetTextPosition(context, lineOrigin.x, lineOrigin.y);
                    CTLineRef line = CFArrayGetValueAtIndex(lines, lineIndex);
                    
                    BOOL shouldDrawLine = YES;
                    if (lineIndex == numberOfLines - 1 )
                    {
                        // Does the last line need truncation?
                        CFRange lastLineRange = CTLineGetStringRange(line);
                        if (lastLineRange.location + lastLineRange.length < attributedString.length)
                        {
                            CTLineTruncationType truncationType = kCTLineTruncationEnd;
                            //加省略号的位置
                            NSUInteger truncationAttributePosition = lastLineRange.location + lastLineRange.length - 1;
                            //获取省略号位置的字符串属性
                            NSDictionary *tokenAttributes = [attributedString attributesAtIndex:truncationAttributePosition
                                                                                 effectiveRange:NULL];
                            //初始化省略号的属性字符串
                            NSAttributedString *tokenString = [[NSAttributedString alloc] initWithString:kEllipsesCharacter
                                                                                              attributes:tokenAttributes];
                            //创建一行
                            CTLineRef truncationToken = CTLineCreateWithAttributedString((CFAttributedStringRef)tokenString);
                            NSMutableAttributedString *truncationString = [[attributedString attributedSubstringFromRange:NSMakeRange(lastLineRange.location, lastLineRange.length)] mutableCopy];
                            
                            if (lastLineRange.length > 0)
                            {
                                // Remove last token
                                [truncationString deleteCharactersInRange:NSMakeRange(lastLineRange.length - 1, 1)];
                            }
                            [truncationString appendAttributedString:tokenString];
                            
                            //创建省略号的行
                            CTLineRef truncationLine = CTLineCreateWithAttributedString((CFAttributedStringRef)truncationString);
                            // 在省略号行的末尾加上省略号
                            CTLineRef truncatedLine = CTLineCreateTruncatedLine(truncationLine, rect.size.width, truncationType, truncationToken);
                            if (!truncatedLine)
                            {
                                // If the line is not as wide as the truncationToken, truncatedLine is NULL
                                truncatedLine = CFRetain(truncationToken);
                            }
                            CFRelease(truncationLine);//CF得自己释放,ARC的不会释放
                            CFRelease(truncationToken);
                            
                            CTLineDraw(truncatedLine, context);
                            CFRelease(truncatedLine);
                            
                            shouldDrawLine = NO;
                        }
                    }
                    if(shouldDrawLine)
                    {
                        CTLineDraw(line, context);
                    }
                }
            }
            else
            {
                CTFrameDraw(_textFrame,context);
            }
        }
        
        CGContextRestoreGState(context);
    }
    

    reply
    0
  • ringa_lee

    ringa_lee2017-04-17 17:34:19

    This requirement is indeed a bit difficult. If it were me, I might use two alternative methods:

    1. Instead of limiting it to 3 lines, it limits the number of words to no more than 3 lines, such as 50 words. Then the string is truncated, spelled with "...", and then "expanded". Use TTTAttributedlabel to add a click event . The number of words can also be determined individually based on several screen widths.

    2. Move the "Expand" outside the label range, limit the numberOfLines of the label to 3, and then "Expand" is a separate button, put it outside...

    If you have to implement this... The way I can think of is to scan the string from beginning to end in a range that is probably 3 lines, such as from 40 words to 60 words, first subString and then calculate the height of boundingRect , until you find that it becomes 4 lines. The previous text fills exactly 3 lines, cut off a few more words, spell "...", and then spell "Expand". But the method of calculating boundingRect is relatively slow, so it is definitely very inefficient. Not very recommended.

    reply
    0
  • 巴扎黑

    巴扎黑2017-04-17 17:34:19

    How did you achieve it?

    reply
    0
  • 巴扎黑

    巴扎黑2017-04-17 17:34:19

    I am also looking for this control

    reply
    0
  • Cancelreply