【问题标题】:Measure String Height in Cocoa在可可中测量字符串高度
【发布时间】:2012-01-20 16:58:53
【问题描述】:

我正在寻找一个高度测量字符串程序,我在另一个堆栈溢出问题中找到了这个程序。它非常适合我的 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 ;
}

【问题讨论】:

    标签: objective-c macos cocoa nsstring nsattributedstring


    【解决方案1】:

    这感觉就像你在重塑 [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: 之间的权衡。)

    【讨论】:

    • 感谢您的回复,boundingRectWithSize 返回的是单行大小的矩形,即使是段落样式,有什么问题吗?
    • 您是否在选项中包含NSStringDrawingUsesLineFragmentOrigin 标志?
    • 谢谢! NSStringDrawingUsesLineFragmentOrigin 为我工作!
    猜你喜欢
    • 2018-07-21
    • 1970-01-01
    • 2020-02-16
    • 1970-01-01
    • 2019-01-14
    • 2017-04-07
    • 2010-10-29
    • 1970-01-01
    • 2021-11-10
    相关资源
    最近更新 更多