我正在尝试根据当前宽度自动调整文本字段/视图的大小。换句话说,我希望宽度保持不变,但根据提供给它的文本调整高度。
它似乎正在工作,但出于某种原因,尽管已经努力将其移回原点,但仍在调整窗口的底部。谁能看到我在这里做错了什么?
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];
编辑:即使手动移动框架,也很明显文字仍然被切断。新调整的尺寸并不完全存在。
这是参考: NSString boundingRectWithSize slightly underestimating the correct width - why? 和 NSTextView or NSTextField automatically resize bounds / frame?
答案 0 :(得分:22)
我遇到了同样的问题。我在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)
另一种Swift 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。
答案 1 :(得分:2)
这有点迂回,但我发现查询NSTextFieldCell
提供的精确/可靠高度比使用[NSAttributedString boundingRectWithSize:options:]
更准确/可靠。
假设感兴趣的字符串已经在NSTextField中并且设置了适当的格式化/包装选项,那么在文本单元格中查询它认为需要适合指定宽度的大小:
NSTextField* textField = ...
NSSize cellSize = [textField.cell cellSizeForBounds:NSMakeRect(0, 0, pathText.frame.size.width, CGFLOAT_MAX)];
cellSize.height
给出了文本在绘制时实际使用的高度。
答案 2 :(得分: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];
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];
产生这个:
答案 3 :(得分:1)
我发现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
}