17

UITableView需要显示一长串类似聊天的对话(通常包含表情符号)中,会发生大小计算错误。

我的问题是,如果一个字符串的长度恰到好处,并且我使用sizeWithFont,我在第一次测量时使用sizewithfont得到的字符串长度不正确,从而导致“换行符”。

我认为这是因为字符串“:-)”比实际的笑脸图标更宽。

证据可以在这里看到:

使用 <code>SizeWithFont</code>

现在,在其他一些堆栈中,有些人声称sizeWithFont只会解释字符串,而不是表情符号,这对我来说没有意义,因为它“最终”会正确......

但他们建议改用 sizeToFit,所以我决定试一试。

使用 SizeToFit

Bam,同样的结果。

有谁知道如何对付这个?是否有boolean检查“标签是否已完成表情符号处理”以便我可以跳过该呼叫?

两次运行同一行没有任何作用,似乎需要绘制视图,然后才sizeWithFont意识到它的错误。

显示的列在- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath自定义单元格上的段中运行。我也可以在完全常规的 UITableViewCell 上复制错误,所以似乎不是这样。

4

3 回答 3

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;

}
于 2014-03-21T11:15:26.263 回答
6

谢谢@SergiSolanellas!这是一个采用属性字符串的版本,因为已经设置了文本和字体,所以缩短了方法。

//
// 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;
}
于 2014-07-23T05:56:06.040 回答
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))

作为代码,您需要分配三个属性。

于 2018-09-03T04:41:05.210 回答