搜尋

首頁  >  問答  >  主體

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

如题

比如

这个UIlabel 本该显示成

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

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

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

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

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

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

天蓬老师天蓬老师2772 天前1231

全部回覆(4)我來回復

  • 天蓬老师

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

    樓上限製字數是不實際的,漢字一樣的寬度,但是其他字符寬度不一致,比如1和8,一和1,i和u,W和I……
    這個問題要用CoreText,手動改排版,網路上有這種AttributeLabel先下載程式碼看看,自己完全手寫是很難的,給你看一眼之前我們專案之前網上下的程式碼又自己改的,跟你這個需求有點像,他這個是只加了. ..可以參考,以下這個方法是這個自訂lable的方法

    - (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);
    }
    

    回覆
    0
  • ringa_lee

    ringa_lee2017-04-17 17:34:19

    這個需求確實有點難。如果是我的話,可能會用兩種變通的方法:

    1. 不是限制3 行,而是限制大約不超過3 行的字數,比如50 個字,然後字符串截斷,拼上‘...’,再拼上‘展開’,用TTTAttributedlabel就可以加點擊事件了。字數也可以根據幾種螢幕寬度分別決定。

    2. 把那個『展開』挪到 label 範圍外面去,那個 label 的 numberOfLines 限成 3,然後『展開』是一個單獨的按鈕,放到外面去…

    如果非要實現這個… 我能想到的辦法就是把字串在比較有可能是3 行的範圍內從頭到尾掃一遍,比如從40 個字到60 個字,先subString 再算boundingRect 的height ,直到發現它變成4 行為止。前面的文字剛好填滿 3 行,再多截掉幾個字,拼上『...’,再拼上『展開』。但是算 boundingRect 的那個方法是比較慢的,這樣一定效率很低。不是很建議用。

    回覆
    0
  • 巴扎黑

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

    你怎麼實現的?

    回覆
    0
  • 巴扎黑

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

    我也在找這個控制

    回覆
    0
  • 取消回覆