我正在寻找一个高度测量字符串程序,我在另一个堆栈溢出问题上找到了这个。它适用于我的NSTableViewColumns,其中包含Word Wrap作为换行符 我的问题是,如果我将换行更改为字符换行,如何更新此代码呢?
- (NSSize)sizeForWidth:(float)width
height:(float)height {
NSSize answer = NSZeroSize ;
gNSStringGeometricsTypesetterBehavior = NSTypesetterBehavior_10_2_WithCompatibility;
if ([self length] > 0) {
// Checking for empty string is necessary since Layout Manager will give the nominal
// height of one line if length is 0. Our API specifies 0.0 for an empty string.
NSSize size = NSMakeSize(width, height) ;
NSTextContainer *textContainer = [[NSTextContainer alloc] initWithContainerSize:size] ;
NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:self] ;
NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init] ;
[layoutManager addTextContainer:textContainer] ;
[textStorage addLayoutManager:layoutManager] ;
[layoutManager setHyphenationFactor:0.0] ;
if (gNSStringGeometricsTypesetterBehavior != NSTypesetterLatestBehavior) {
[layoutManager setTypesetterBehavior:gNSStringGeometricsTypesetterBehavior] ;
}
// NSLayoutManager is lazy, so we need the following kludge to force layout:
[layoutManager glyphRangeForTextContainer:textContainer] ;
answer = [layoutManager usedRectForTextContainer:textContainer].size ;
[textStorage release] ;
[textContainer release] ;
[layoutManager release] ;
// In case we changed it above, set typesetterBehavior back
// to the default value.
gNSStringGeometricsTypesetterBehavior = NSTypesetterLatestBehavior ;
}
return answer ;
}
答案 0 :(得分:2)
这感觉就像你正在重塑[NSAttributedString boundingRectWithSize:options:]
(或只是size
)。我在实施中遗漏了什么吗? NSLayoutManager
用于处理快速变化的字符串(例如在文本视图中)。大部分时间都是矫枉过正。你有意绕过它的优化(在你的行中注意到NSLayoutManager
是懒惰的,你的意思是优化:D)
在任何一种情况下,要更改包装行为,您需要修改NSAttributedString
本身。包装是paragraph style的一部分。这样的事情(未经测试;可能无法编译):
// Lazy here. I'm assuming the entire string has the same style
NSMutableParagraphStyle *style = [[self attribute:NSParagraphStyleAttributeName atIndex:0 effectiveRange:NULL] mutableCopy];
[style setLineBreakMode:NSLineBreakByCharWrapping];
NSAttributedString *charWrappedString = [self mutableCopy];
[charWrappedString setAttribute:NSParagraphStyleAttributeName value:style range:NSMakeRange(0, [self length]];
NSRect boundingRect = [self boundingRectWithSize:NSMakeSize(width, height) options:0];
NSSize size = boundRect.size;
[style release];
[charWrappedString release];
return size;
样式有点棘手,因为它们包含了几个内容,但你必须将它们全部放在一起。因此,如果属性字符串中存在不同的样式,则必须循环遍历字符串,处理每个effectiveRange
。 (您需要阅读文档以了解attributesAtIndex:effectiveRange:
和attributesAtIndex:longestEffectiveRange:inRange:
之间的权衡。)