iOS關於UITextView計算文本高度不准確的坑


問題: 字段由后端控制,里面出現換行的時候 \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;

經過這么一番折騰之后,文本正常顯示了 🤬

終極解決方案

2020年6月24日 其實根本不用這么麻煩,系統自適應方法即可計算准確,評論區已給出答案

參考博客:

boundingRectWithSize計算文字高度不准問題
使用boundingRectWithSize計算內容高度的坑


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM