我們知道當(dāng)UILabel
顯示不下內(nèi)容時糕殉,會自動截?cái)嗵幚砬匮保覀冞€可以用lineBreakMode
來修改截?cái)喾绞秸贫.?dāng)我們限定只能截?cái)嗄承┳址麜r,系統(tǒng)提供的截?cái)喾绞骄筒荒軡M足了记餐。
自定義截?cái)嘧址麜r驮樊,就會遇到一個問題,固定寬度下能顯示多少字符串片酝?
使用場景
偶爾收到了微信的專屬紅包囚衔,發(fā)現(xiàn)當(dāng)微信名或備注較長時,會將用戶名截?cái)囡@示雕沿。
微信專屬紅包练湿,昵稱較長時顯示如下:
給ABCDEFGHI...的專屬紅包
ABCDEFGHI...已領(lǐng)取
實(shí)現(xiàn)邏輯分析
微信紅包氣泡寬度是相對固定的,所以紅包狀態(tài)的寬度也是固定的审轮。當(dāng)用戶名過長時肥哎,要保證其他字符能完整顯示,只能截?cái)嘤脩裘?/p>
//其他字符
給xxx的專屬紅包
總寬度 = 其他字符寬度 + 用戶名寬度(可截?cái)啵?
由上我們知道疾渣,算出其他字符的寬度后篡诽,就能得到用戶名寬度。拿到用戶名可顯示的寬度后榴捡,怎么知道能顯示多少內(nèi)容呢杈女?
實(shí)現(xiàn)流程
查資料發(fā)現(xiàn)可以用CTFrame獲取可見字符串范圍 CTFrameGetVisibleStringRange
CFRange CTFrameGetVisibleStringRange(CTFrameRef frame);
由上定義,我們還需要創(chuàng)建一個CTFrameRef
吊圾,需用到 CTFramesetterCreateFrame
CTFrameRef CTFramesetterCreateFrame(CTFramesetterRef framesetter, CFRange stringRange, CGPathRef path, CFDictionaryRef frameAttributes);
通過path
參數(shù)达椰,我們可以傳入寬度限制,即可得到固定寬度下的可見字符串范圍项乒。
上代碼
最好寫在NSString
的Category
中啰劲,需要導(dǎo)入CoreText
框架。
注意:其中path的高度需大于font.lineHeight
檀何,小于2倍font.lineHeight
蝇裤,當(dāng)大于2倍font.lineHeight
時趁尼,將按照多行來計(jì)算可顯示的內(nèi)容。
#import "NSString+STExtension.h"
#import <CoreText/CoreText.h>
/// 獲取固定寬度下的可見字符串
/// @param width 寬度
/// @param font 字體
/// @param showEllipsis 結(jié)尾是否展示省略號
- (NSString *)getVisibleStringWithWidth:(CGFloat)width font:(UIFont*)font showEllipsis:(bool)showEllipsis
{
if (width == 0) {
return @"";
}
NSMutableParagraphStyle *p = [[NSMutableParagraphStyle alloc] init];
p.lineBreakMode = NSLineBreakByCharWrapping;
NSAttributedString *namesAtt = [[NSAttributedString alloc] initWithString:self attributes:@{NSFontAttributeName:font, NSParagraphStyleAttributeName:p}];
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)namesAtt);
UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, width, font.lineHeight + 1.0)];
CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, self.length), path.CGPath, NULL);
CFRange range = CTFrameGetVisibleStringRange(frame);
CFRelease(framesetter);
CFRelease(frame);
NSString *resultStr = [self substringWithRange:NSMakeRange(range.location, range.length)];
if (showEllipsis && resultStr.length < self.length && resultStr.length > 0) {
resultStr = [resultStr stringByReplacingCharactersInRange:NSMakeRange(resultStr.length - 1, 1) withString:@"..."];
}
return resultStr;
}
最后
感謝閱讀猖辫,有問題歡迎討論。