2012-08-23 32 views
12

我试图根据当前宽度自动调整文本字段/视图的大小。换句话说,我希望宽度保持不变,但根据提供给它的文本调整高度。NSString boundingRectWithSize稍微低估了正确的高度 - 为什么?

它似乎正在工作,但出于某种原因,尽管努力手动将其移回,我的窗口的底部对齐。任何人都可以看到我在这里做错了吗?

enter image description here

NSString *temp = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer vel felis nec massa ultricies blandit non id arcu. Sed enim est, facilisis a feugiat in, consectetur eget arcu. Aenean rutrum, lacus id euismod congue, nisl erat vulputate lectus, non faucibus tortor purus sed sem. Donec tempor dui egestas velit auctor vitae faucibus diam facilisis. Morbi convallis nulla quis est pulvinar quis ultricies sem sollicitudin."; 

myText.stringValue = temp; 

NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys: 
          [NSFont systemFontOfSize:12], NSFontAttributeName, 
          [NSParagraphStyle defaultParagraphStyle], NSParagraphStyleAttributeName, 
          nil]; 

NSSize size = NSMakeSize(window.frame.size.width, 200); 
myText.frame = [temp boundingRectWithSize:size options:NSLineBreakByWordWrapping | NSStringDrawingUsesLineFragmentOrigin attributes:attributes]; 

编辑:即使手动移动很明显,文本还是会被切断框架。新调整的大小不是那里。 enter image description here

这是参照: NSString boundingRectWithSize slightly underestimating the correct width - why?NSTextView or NSTextField automatically resize bounds/frame?

+0

也许从200改变高度的东西的方式大,使得框架大小知道垂直增长。 – rein

+0

@rein我一直在玩,尽管它实际上重新调整了新框架的底部仍然剪裁文本的大小。新的框架不够大。查看更新的问题以获取新的屏幕截图。 –

回答

15

我有同样的问题。我发现在the Documentation如下:

要正确绘制和大小多行文本,在选项参数传递 NSStringDrawingUsesLineFragmentOrigin。

此方法返回小数大小(在返回的CGRect的 的大小组件中);若要使用返回的大小来调整视图大小,则必须使用ceil函数将 的值提高到最接近的较大整数。

因此,这解决了这个问题对我来说:

CGRect rect = [myLabel.text boundingRectWithSize:CGSizeMake(myLabel.frame.size.width, CGFLOAT_MAX) 
                options:NSStringDrawingUsesLineFragmentOrigin 
               attributes:@{NSFontAttributeName: myLabel.font} 
                context:nil]; 
rect.size.width = ceil(rect.size.width); 
rect.size.height = ceil(rect.size.height); 

更新(SWIFT 3)

替代斯威夫特3的方式来做到这一点是:

let size = myLabel.text!.size(
    attributes: [NSFontAttributeName: myLabel.font] 
) 
let rect = CGSize(
    width: ceil(size.width), 
    height: ceil(size.height) 
) 

见针对Objective-C示例的this answer

+0

谢谢你,帮了我很多 – phyzalis

+2

OR'ing与NSLineBreakByWordWrapping是无效的,并不适合我反正。它不是NSStringDrawingOptions枚举的成员。 – iphone007

+0

嗯..你说得对!你用'NSStringDrawingUsesLineFragmentOrigin'来试试吗?它有用吗?然后我会编辑该片段。 –

1

这是我结束了去(至少暂时),它似乎很好地工作,但我还是觉得有是一个更好的方法来实现这一点。

NSString *temp = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer vel felis nec massa ultricies blandit non id arcu. Sed enim est. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer vel felis nec massa ultricies blandit non id arcu. Sed enim est."; 

myText.stringValue = temp; 

NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys: 
          [NSFont systemFontOfSize:12], NSFontAttributeName, 
          [NSParagraphStyle defaultParagraphStyle], NSParagraphStyleAttributeName, 
          nil]; 

NSSize size = NSMakeSize(window.frame.size.width, MAXFLOAT); 


myText.frame = [temp boundingRectWithSize:size options:NSLineBreakByWordWrapping | NSStringDrawingUsesLineFragmentOrigin attributes:attributes]; 

// Keep current width but add some more on the bottom 
NSSize tF = myText.frame.size; 
[myText setFrameSize:NSMakeSize(tF.width, tF.height + 35)]; 

[myText setFrameOrigin:NSMakePoint((NSWidth(window.frame) - NSWidth(myText.frame))/2, 
            (NSHeight(window.frame) - NSHeight(myText.frame) - 20))]; 

[myText setAutoresizingMask:NSViewMinXMargin | NSViewMaxXMargin | NSViewMinYMargin | NSViewMaxYMargin]; 

产生以下:

enter image description here

2

这是一个有点迂回,但我发现查询NSTextFieldCell给出比使用[NSAttributedString boundingRectWithSize:options:] /高度可靠的结果更准确。

假设感兴趣的字串已经是一个的NSTextField以适当的格式/包设置选项,然后查询它的想法的大小,它需要以适应特定的宽度文本单元:

NSTextField* textField = ...

NSSize cellSize = [textField.cell cellSizeForBounds:NSMakeRect(0, 0, pathText.frame.size.width, CGFLOAT_MAX)];

cellSize.height给出了文本在绘制时实际使用的高度。

0

我发现的NSString#boundingRectWithSize是从来没有完全正确的,这似乎运作良好的唯一事情是这里所描述的: https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/TextLayout/Tasks/StringHeight.html

class func sizeForString(_ text : String, withFont font: NSFont, inWidth maxWidth: CGFloat) -> NSSize { 
    let textStorage = NSTextStorage(string: text) 
    let textContainer = NSTextContainer(containerSize: NSSize(width: maxWidth, height: CGFloat.greatestFiniteMagnitude)) 
    let layoutManager = NSLayoutManager() 
    layoutManager.addTextContainer(textContainer) 
    textStorage.addLayoutManager(layoutManager) 
    textStorage.addAttribute(NSFontAttributeName, value: font, range: NSMakeRange(0, textStorage.length)) 
textContainer.lineFragmentPadding = 0 
    layoutManager.glyphRange(for: textContainer) 
    return layoutManager.usedRect(for: textContainer).size 
} 
相关问题