博客> DYFoldLabel -- 一行代码实现折叠label
DYFoldLabel -- 一行代码实现折叠label
2019-09-21 16:03 评论:0 阅读:525 duyi56432
ios 文字折叠

源码在这里 ,使用Cocoapod:

pod 'DYFoldLabel'   

简介

设置一段显示不完整文字省略号后的折叠按钮。 先看效果: 效果图.gif

功能亮点: 1.用category实现,无需继承UILabel。 2.可以兼容自动布局。 3.解决大多数第三方文字点击在特殊情况有误问题。

方法调用

/**

 设置一段显示不完整文字省略号后的折叠按钮。

 @param foldText 折叠按钮文字
 @param font 折叠按钮文字字体
 @param color 折叠按钮文字颜色
 @param block 折叠按钮回调block,传入nil禁止点击
 */
- (void)setFoldText:(NSString *)foldText
           textFont:(UIFont *)font
          textColor:(UIColor *)color
         clickBlock:(DYFoldBtnClickBlock)block;

/**
 设置是否展开label。
 */
- (void)foldLabel:(BOOL)folded;

核心思路:

1.计算第几行结束。因为折叠文字的font可以和文本不一致,最后一行可能比其他行会占用更多行的空间。

- (NSInteger)lineReplaceWithLine:(CFIndex)lineCount lines:(CFArrayRef)lines fontDiff:(CGFloat)fontDiff {
    //计算单行高度
    CGFloat ascent = 0,descent = 0,leading = 0;
    CTLineRef line = CFArrayGetValueAtIndex(lines, 0);
    CTLineGetTypographicBounds(line, &ascent, &descent, &leading);
    CGFloat lineHeight = ascent + descent + leading;

    //计算最后一行的index。
    //eg:如果正常可以显示4行,折叠文字的font.poinSize = 20,正常文本的font.poinSize = 15,
    //那么最后一行会占用两行的高度,index就会比实际行数少1。
    NSInteger lineIndex = 0,index = 0;
    NSInteger number = self.numberOfLines - 1;
    CGFloat totalLineHeight = 0;
    while (totalLineHeight < (lineHeight + fontDiff) && lineCount >= index) {
        if (totalLineHeight < (lineHeight + leading)) {
            index++;
        }
        totalLineHeight = lineHeight * index;
    }
    lineIndex = lineCount - index;//这里需要+1,因为最后一行没计算在内,又因为数组最后一个元素索引=count-1,所以+1抵消
    lineIndex = (self.numberOfLines > 0) ? MIN(lineIndex, number) : lineCount;
    return lineIndex;
}

2.计算被替换文字的长度。要加省略号以及折叠文字,需要替换掉最后一行最后一部分文字。

- (NSInteger)subLenthWithString:(NSMutableAttributedString *)string lineRange:(NSRange)range text:(NSString *)text textFont:(UIFont *)font{
    //折叠文字宽度
    CGFloat foldWidth = [self dy_sizeForText:text Font:font size:CGSizeMake(self.bounds.size.width, CGFLOAT_MAX) mode:0].width;
    CGFloat spaceTextWidth = 0.0;
    NSInteger index = 0;
    while (spaceTextWidth < foldWidth xss=removed xss=removed xss=removed xss=removed xss=removed xss=removed xss=removed xss=removed xss=removed xss=removed xss=removed xss=removed xss=removed xss=removed xss=removed xss=removed xss=removed xss=removed>= (self.bounds.size.height * 0.5 - textHeight * 0.5 )) {
        CFIndex index = CTLineGetStringIndexForPosition(endLine, clickPoint);
        NSString *foldText = objc_getAssociatedObject(self, "foldText");
        NSRange range = NSMakeRange(self.text.length - foldText.length, foldText.length);
        //判断点击的字符是否在需要处理点击事件的字符串范围内
        if (range.location <= index) {
            if (clickBlock) {
                clickBlock();
            }
        }
    }
}

如果对你有帮助的话,能给 DYFoldLabel 打赏一个小星星吗

收藏
1
sina weixin mail 回到顶部