cocoa - NSStackView 的 View 间距不正确

标签 cocoa

我一直在使用 NSStackView(在 OS X 10.9.4 上),但有点卡住了。本质上,我正在创建一个页脚 View 并向该页脚添加一个堆栈 View 。我希望将一些项目分组到页脚的左侧,并将一些项目分组到右侧。我认为这可以通过根据需要将 View 分配给前导和尾随重力来完成。但是,我似乎无法达到预期的效果。

NSView* footerView = [[NSView alloc] initWithFrame:CGRectZero];
footerView.translatesAutoresizingMaskIntoConstraints = NO;
self.footerView = footerView;

NSStackView* stackView = [[NSStackView alloc] init];
stackView.translatesAutoresizingMaskIntoConstraints = NO;
self.stackView = stackView;
[self.footerView addSubview:stackView];

NSTextField* firstTextField = [[NSTextField alloc] init];
firstTextField.translatesAutoresizingMaskIntoConstraints = NO;
firstTextField.bezeled = NO;
firstTextField.editable = NO;
firstTextField.stringValue = @"One";
self.firstTextField = firstTextField;
[self.stackView addView:firstTextField inGravity:NSStackViewGravityLeading];

NSTextField* secondTextField = [[NSTextField alloc] init];
secondTextField.translatesAutoresizingMaskIntoConstraints = NO;
secondTextField.bezeled = NO;
secondTextField.editable = NO;
secondTextField.stringValue = @"Two";
self.secondTextField = secondTextField;
[self.stackView addView:secondTextField
              inGravity:NSStackViewGravityLeading];

NSTextField* thirdTextField = [[NSTextField alloc] init];
thirdTextField.translatesAutoresizingMaskIntoConstraints = NO;
thirdTextField.bezeled = NO;
thirdTextField.editable = NO;
thirdTextField.stringValue = @"Three";
self.thirdTextField = thirdTextField;
[self.stackView addView:thirdTextField inGravity:NSStackViewGravityLeading];

NSTextField* fourthTextField = [[NSTextField alloc] init];
fourthTextField.translatesAutoresizingMaskIntoConstraints = NO;
fourthTextField.bezeled = NO;
fourthTextField.editable = NO;
fourthTextField.stringValue = @"Four";
self.fourthTextFeild = fourthTextField;
[self.stackView addView:fourthTextField
              inGravity:NSStackViewGravityTrailing];

NSTextField* fifthTextField = [[NSTextField alloc] init];
fifthTextField.translatesAutoresizingMaskIntoConstraints = NO;
fifthTextField.bezeled = NO;
fifthTextField.editable = NO;
fifthTextField.stringValue = @"Five";
self.fifthTextField = fifthTextField;
[self.stackView addView:fifthTextField
              inGravity:NSStackViewGravityTrailing];

[self.window.contentView addSubview:footerView];

NSDictionary* views = @{
    @"footerView" : self.footerView,
    @"stackView" : self.stackView
};
[self.window.contentView
    addConstraints:[NSLayoutConstraint
                       constraintsWithVisualFormat:@"V:[footerView(==30)]|"
                                           options:0
                                           metrics:nil
                                             views:views]];

[self.window.contentView
    addConstraints:[NSLayoutConstraint
                       constraintsWithVisualFormat:@"H:|[footerView]|"
                                           options:0
                                           metrics:nil
                                             views:views]];
[self.footerView
    addConstraints:[NSLayoutConstraint
                       constraintsWithVisualFormat:@"H:|-[stackView]-|"
                                           options:0
                                           metrics:nil
                                             views:views]];
[self.footerView
    addConstraints:[NSLayoutConstraint
                       constraintsWithVisualFormat:@"V:|[stackView]|"
                                           options:0
                                           metrics:nil
                                             views:views]];

如果我只添加前三个文本字段,那么它们都会在前导区域中正确分组在一起。 Only leading area views

但是,当我添加尾随区域 View 时,前导区域中的 View 会跳向尾随区域 Leading and Trailing Views

从 NSStackView 的 spacer 属性文档中,我看到了

In combination, these constraints result in the following typical stack view behavior: In a stack view whose hasEqualSpacing property is set to NO (the default) and whose hugging priority is left at NSLayoutPriorityDefaultLow (the default), views within a gravity area remain a fixed distance from each other (equal to the value of the spacing property), and the distance between gravity areas grows and shrinks as the stack view grows and shrinks along its layout direction axis.

但是,这似乎并没有发生。重力区域(前导)内 View 之间的间距不是恒定的,并且,它似乎将其设置为间隔距离,而不是增大/缩小重力区域之间的距离。

我希望一、二、三出现在页脚左侧(按默认距离间隔),四、五出现在页脚右侧。我可以尝试通过使用两个不同的堆栈 View (一个用于前导区域,另一个用于尾部区域)来实现这一点,但是,我认为这应该可以通过单个堆栈 View 和重力区域来实现。希望对此有一些指导。谢谢

最佳答案

NSStackViewspacing 属性的文档显示重力区域间间距设置为 spacing 值(默认为 8点)以及堆栈 View 在该方向上配置的拥抱优先级(默认为 NSLayoutPriorityDefaultLow)。

如果文本字段的内容拥抱优先级低于该值,则自动布局系统将更愿意拉伸(stretch)其中一个而不是重力区域间的间距。这就是为什么其中一个文本字段被拉伸(stretch),如您的问题所示。 (如果文本字段具有相同的内容拥抱优先级,则拉伸(stretch)哪个文本字段是任意的,并且可以随时更改。)

如果文本字段的内容拥抱优先级等于堆栈 View 的拥抱优先级,那么拉伸(stretch)的内容是任意的。它可以是文本字段之一,也可以是重力区域间的间距。

您希望使文本字段具有更高的内容拥抱优先级,正如您在答案中所指出的那样。它不需要是 NSLayoutPriorityDragThatCanResizeWindow。它可以是高于堆栈 View 的拥抱优先级的任何值。

正如您在答案中所报告的那样,这与限制窗口缩小无关。

如果您希望堆栈 View 允许自身缩小到比其 subview 和 subview 之间的间距指示的尺寸更窄,您有两个选择。首先,您可以使用 -setClippingResistancePriority:forOrientation: 将其剪切阻力优先级设置为低于 NSLayoutPriorityWindowSizeStayPut。这将导致堆栈 View 允许 View 被剪切或分离。发生哪一种情况取决于 View 的可见性优先级,由 setVisibilityPriority:forView: 设置。默认情况下,所有 View 的可见性优先级均为 NSStackViewVisibilityPriorityMustHold,这意味着它们不会分离,但会被剪裁。

因此,如果您希望分离 View ,则应该更改它们的可见性优先级。您应该对优先级进行排序,以指示相对于其他 View (较高),您希望首先分离哪些 View (较低的可见性优先级)。

另一种方法是将 subview 的抗压缩优先级设置为低于NSLayoutPriorityWindowSizeStayPut。这意味着自动布局系统将压缩文本字段,通常用省略号(“...”)截断它们。您可能希望对文本字段的压缩阻力优先级进行排序,以确定它们的压缩顺序,否则它将是任意的(甚至可能随时发生变化)。您可能还想在文本字段上设置最小宽度限制,因为在某些时候,让文本字段可见但没有空间显示任何有意义的内容看起来很糟糕。

您可以通过使文本字段的压缩阻力低于堆栈 View 的剪切阻力来组合这两种方法。文本字段的最小宽度限制可能会很高,甚至是必需的;无论如何,都高于堆栈 View 的剪切阻力。因此,当窗口和堆栈 View 缩小时,文本字段将压缩直到达到最小宽度,然后下一个文本字段将压缩,依此类推。当所有文本字段都达到最小宽度时,堆栈 View 将剪切或分离它们(按可见性优先顺序)直到它们再次适合。

关于cocoa - NSStackView 的 View 间距不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28971317/

相关文章:

objective-c - 在 Cocoa 应用程序中处理 Cmd-Q(以编程方式处理菜单项 'Quit Application')

objective-c - NSImage initWithContentsOfFile : display progress

objective-c - 寻找 cocoa 谷歌地图包装器框架

cocoa - Mac OS X (Cocoa) 应用程序的自动化 UI 测试工具

Cocoa:获取鼠标在屏幕上的当前位置

objective-c - 文本字段可以自动识别电话号码和链接吗?

macos - OS X 应用程序无需激活即可运行?

macos - 如何在不关闭窗口的情况下关闭文档?

objective-c - 类方法等价于 -respondsToSelector :

objective-c - Mac OS X 10.10 重新排序首选网络