首页 > 技术文章 > iOS关于UITextView计算文本高度不准确的坑

wgb1234 2020-03-09 17:29 原文

问题: 字段由后端控制,里面出现换行的时候 \r\n是成对出现的 , 转义字符并未纳入字符串的计算范围 。。。 所以导致显示不全的bug

解决方案一:

由于这个方法计算字符串的大小的通过取得字符串的size来计算, 如果你计算的字符串中包含\r\n 这样的字符,也只会把它当成字符来计算。但是在显示的时候就是\n是转义字符,那么显示的计算的高度就不一样了,所以可以采用:计算的高度 = boundingRectWithSize计算出来的高度 + \r\n转义字符出现的个数 * 单行文本的高度。


///MARK:- 查询字串出现的次数 方法二
- (NSInteger)searchSubStringCountWithSubString:(NSString *)subStr
{
    NSUInteger count = 0, length = [subStr length];
    NSRange range = NSMakeRange(0, length);
    while(range.location != NSNotFound){
        range = [self rangeOfString: subStr options:0 range:range];
        if(range.location != NSNotFound){
            range = NSMakeRange(range.location + range.length, length - (range.location + range.length));
            count++;
        }
    }
    return count;
}


解决方案二:

采用UILabel来展示文本就没有这个坑,主要看自己选择,毕竟有些特性只有UITextView才有的


@implementation NSString (Extension)

///MARK:- 查询字串出现的次数 方法一
- (NSInteger)countOccurencesOfString:(NSString*)searchString {
    NSInteger strCount = [self length] - [[self stringByReplacingOccurrencesOfString:searchString withString:@""] length];
    return strCount / [searchString length];
}

///MARK:- 查询字串出现的次数 方法二
- (NSInteger)searchSubStringCountWithSubString:(NSString *)subStr
{
    NSUInteger count = 0, length = [subStr length];
    NSRange range = NSMakeRange(0, length);
    while(range.location != NSNotFound){
        range = [self rangeOfString: subStr options:0 range:range];
        if(range.location != NSNotFound){
            range = NSMakeRange(range.location + range.length, length - (range.location + range.length));
            count++;
        }
    }
    return count;
}


//计算单行文本宽度和高度,返回值与`UIFont.lineHeight`一致  [手动滑稽]方块字
- (CGSize)singleLineSizeWithText:(UIFont *)font{
    return [self sizeWithAttributes:@{NSFontAttributeName:font}];
}
@end

项目中展示控件使用的是UITextView 文本中包含\r\n来换行 同一个PHP后端这种既定的规则应该不会经常变。
所以:

    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
    [paragraphStyle setLineBreakMode:NSLineBreakByCharWrapping];
    paragraphStyle.lineSpacing = 5;// 字体的行间距
    paragraphStyle.alignment = NSTextAlignmentLeft;
    NSDictionary *attributes = @{
                                 NSForegroundColorAttributeName : [UIColor whiteColor],
                                 NSParagraphStyleAttributeName : paragraphStyle,
                                 NSFontAttributeName : KFontSize(13)
                                 };
    //出现`\r` `\n` 关于计算高度不准确的问题 https://www.jianshu.com/p/c615a76dace2
    CGFloat textX = 35;
    CGFloat textW = KWIDTH - textX*2;
    NSString *realText = shareModel.tips ;
    NSInteger warpRowCount = [realText searchSubStringCountOccurencesOfString:@"\r\n"];
    CGFloat singleLineHeight = [@"哈哈哈哈哈哈哈哈哈" singleLineSizeWithText:KFontSize(13)].height + 5;
    CGFloat addHeight = warpRowCount *singleLineHeight;
    
    CGFloat textH = [realText boundingRectWithSize:CGSizeMake(textW, MAXFLOAT) options:
                     NSStringDrawingUsesLineFragmentOrigin |
                     NSStringDrawingUsesFontLeading
                                               attributes: attributes context:nil].size.height + 0.5 + addHeight;
    self.textView.frame = CGRectMake(textX, 0, textW , textH);
    NSMutableAttributedString * attributeStr = [[NSMutableAttributedString alloc] initWithString: realText  attributes:attributes];
    self.textView.attributedText = attributeStr;

经过这么一番折腾之后,文本正常显示了

推荐阅读