【发布时间】:2012-05-05 16:15:10
【问题描述】:
Lion 中的自动布局应该让文本字段(以及标签)随着它所包含的文本一起增长变得相当简单。
文本字段设置为在 Interface Builder 中换行。
有什么简单可靠的方法来做到这一点?
【问题讨论】:
标签: cocoa nstextfield autolayout
Lion 中的自动布局应该让文本字段(以及标签)随着它所包含的文本一起增长变得相当简单。
文本字段设置为在 Interface Builder 中换行。
有什么简单可靠的方法来做到这一点?
【问题讨论】:
标签: cocoa nstextfield autolayout
NSView 中的 intrinsicContentSize 方法返回视图本身认为的固有内容大小。
NSTextField 计算此值时不考虑其单元格的 wraps 属性,因此它会报告文本在单行中的尺寸。
因此,NSTextField 的自定义子类可以覆盖此方法以返回更好的值,例如单元格的 cellSizeForBounds: 方法提供的值:
-(NSSize)intrinsicContentSize
{
if ( ![self.cell wraps] ) {
return [super intrinsicContentSize];
}
NSRect frame = [self frame];
CGFloat width = frame.size.width;
// Make the frame very high, while keeping the width
frame.size.height = CGFLOAT_MAX;
// Calculate new height within the frame
// with practically infinite height.
CGFloat height = [self.cell cellSizeForBounds: frame].height;
return NSMakeSize(width, height);
}
// you need to invalidate the layout on text change, else it wouldn't grow by changing the text
- (void)textDidChange:(NSNotification *)notification
{
[super textDidChange:notification];
[self invalidateIntrinsicContentSize];
}
【讨论】:
基于 Peter Lapisu 的 Objective-C 帖子
子类NSTextField,在下面添加代码。
override var intrinsicContentSize: NSSize {
// Guard the cell exists and wraps
guard let cell = self.cell, cell.wraps else {return super.intrinsicContentSize}
// Use intrinsic width to jive with autolayout
let width = super.intrinsicContentSize.width
// Set the frame height to a reasonable number
self.frame.size.height = 750.0
// Calcuate height
let height = cell.cellSize(forBounds: self.frame).height
return NSMakeSize(width, height);
}
override func textDidChange(_ notification: Notification) {
super.textDidChange(notification)
super.invalidateIntrinsicContentSize()
}
将self.frame.size.height 设置为“合理的数字”避免在使用FLT_MAX、CGFloat.greatestFiniteMagnitude 或大数字时出现一些错误。当用户选择突出显示字段中的文本时,会在操作过程中出现错误,他们可以将滚动向上和向下拖动到无穷大。此外,当用户输入文本时,NSTextField 会被置空,直到用户结束编辑。最后,如果用户选择了NSTextField,然后尝试调整窗口大小,如果self.frame.size.height 的值太大,窗口就会挂起。
【讨论】:
接受的答案是基于对intrinsicContentSize 的操作,但并非在所有情况下都需要这样做。如果 (a) 你给文本域一个preferredMaxLayoutWidth 和 (b) 使这个域不是editable,自动布局会增加和缩小文本域的高度。这些步骤使文本字段能够确定其固有宽度并计算自动布局所需的高度。有关详细信息,请参阅 this answer 和 this answer。
更模糊的是,如果您在字段上使用绑定并且未能清除 Conditionally Sets Editable 选项,则自动布局将中断对文本字段的 editable 属性的依赖性。
【讨论】: