在UITableView
中,需要显示一长串聊天对话(通常包含表情符号),会出现大小计算错误。
我的问题是,如果字符串的长度恰到好处,并且我使用sizeWithFont
,那么我使用sizewithfont
进行第一次测量时会得到一个不正确的字符串长度,导致“换行”
我认为这是因为字符串“:-)”比实际的笑脸图标更宽。
证据可以在这里看到:
现在,在其他一些堆栈中,有些人声称sizeWithFont
只会考虑字符串,而不是表情符号,这对我来说没有意义,因为它最终“正确”......
但他们建议改用sizeToFit,所以我决定试一试。
Bam,结果相同。
有谁知道怎么反击这个?是否有boolean
来检查“标签是否已完成表情符号处理”,以便我可以跳过该通话?
在sizeWithFont
意识到错误之前,两次运行相同的行没有任何作用,似乎需要绘制视图。
显示的列在自定义单元格的- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
段中运行。我也可以在一个非常规的UITableViewCell上复制错误,所以这似乎不是它。
答案 0 :(得分:13)
- (CGFloat)heightStringWithEmojis:(NSString*)str fontType:(UIFont *)uiFont ForWidth:(CGFloat)width {
// Get text
CFMutableAttributedStringRef attrString = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0);
CFAttributedStringReplaceString (attrString, CFRangeMake(0, 0), (CFStringRef) str );
CFIndex stringLength = CFStringGetLength((CFStringRef) attrString);
// Change font
CTFontRef ctFont = CTFontCreateWithName((__bridge CFStringRef) uiFont.fontName, uiFont.pointSize, NULL);
CFAttributedStringSetAttribute(attrString, CFRangeMake(0, stringLength), kCTFontAttributeName, ctFont);
// Calc the size
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(attrString);
CFRange fitRange;
CGSize frameSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetter, CFRangeMake(0, 0), NULL, CGSizeMake(width, CGFLOAT_MAX), &fitRange);
CFRelease(ctFont);
CFRelease(framesetter);
CFRelease(attrString);
return frameSize.height + 10;
}
答案 1 :(得分:6)
谢谢@SergiSolanellas!这是一个带有referencedString的版本,缩短了方法,因为文本和字体已经设置好了。
//
// Given an attributed string that may have emoji characters and the width of
// the display area, return the required display height.
//
- (CGFloat)heightForAttributedStringWithEmojis:(NSAttributedString *)attributedString forWidth:(CGFloat)width {
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attributedString);
CFRange fitRange;
CGSize frameSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetter, CFRangeMake(0, 0), NULL, CGSizeMake(width, CGFLOAT_MAX), &fitRange);
CFRelease(framesetter);
return frameSize.height;
}
答案 2 :(得分:0)
我正在使用UILabel
sizeThatFits(_ size:CGSize)-> CGSize
对我有用。
我的代码
let tempLabel = UILabel()
tempLabel.font = font
tempLabel.attributedText = attText
tempLabel.numberOfLines = 0
let size = tempLabel.sizeThatFits(CGSize(width: 200, height:CGFloat.greatestFiniteMagnitude))
作为代码,您需要分配三个属性。