随着窗口变小,OSX 自动布局无法重绘某些控件

Posted

技术标签:

【中文标题】随着窗口变小,OSX 自动布局无法重绘某些控件【英文标题】:OSX Autolayout Fails to Redraw Some Controls As Window Gets Smaller 【发布时间】:2015-04-24 19:46:09 【问题描述】:

我有一个使用自动布局的视图的 xib 文件。随着视图变大,沿窗口下边缘放置的 3 个按钮都按预期向下移动,与窗口下边缘保持恒定距离。但是随着窗口变小,三个按钮不会移动,最终消失,只有当窗口变大(即使是最小的量)时,它们才会重新绘制。下面的动画 gif 显示了它的外观。 更新:这是一个较新的屏幕截图。请注意,当窗口调整大小时,不仅按钮而且分段控件都无法正确绘制。

约束是我一直关注的地方。例如,标记为“Check All”的按钮有 2 个与其垂直位置相关的约束。其他两个与前沿放置有关,我没有将它们包括在此处。

一位评论者要求我提供有关限制的详细信息。第一个图像显示了“检查全部”按钮上的约束。 (另一个按钮有类似的约束。)。约束都是优先级 1000,与原帖中的略有不同。

下一个屏幕截图显示了 Check All 按钮上方表格上的约束。

我在应用委托上有这个代码:

- (void) windowDidResize: (NSNotification *) notification

    _masterViewController.view.frame = ((NSView*)_window.contentView).bounds;

如果我在此方法中显式添加代码以重绘未正确绘制的按钮和分段控件,那么一切看起来都很棒。这解决了这个问题,但它仍然不能解释为什么会发生这种情况。 更新:它告诉我这可能不是我最初怀疑的自动布局问题,而是与重绘周期有关。

有人知道为什么会这样吗?

【问题讨论】:

您是否有任何自定义视图类(不小心?)覆盖了与自动布局或框架设置相关的任何NSView 方法(例如-layout-layoutSubtreeIfNeeded-setFrame...) ?同样,您是否正在使用 NSWindow 的自定义子类来执行类似操作?重现问题时是否有任何内容记录到控制台? 我没有重写任何这些方法或类似的东西。我确实有一些在调整大小通知上调用 NSLog 的东西,我删除了它。但是,应用的行为没有变化。 我终于找到了一种解决方法,方法是更改​​ windowDidResize 以在窗口缩小时为每个未正确重绘的控件调用 -setNeedsDisplay: YES。问题仍未解决,但这暂时可以解决问题。 能不能同时添加自动布局约束的截图? 添加了自动布局约束。从我的观察来看,这可能与自动布局设置无关或几乎没有关系,而更多地与自动布局代码重绘控件时有关。 【参考方案1】:

在您的代码中,无论您在哪里执行与[_window.contentView addSubview:_masterViewController.view] 等效的操作,您都应该执行以下操作:

[_window.contentView addSubview:_masterViewController.view];
_masterViewController.view.translatesAutoresizingMaskIntoConstraints = NO; // optional if you already turned it off in the NIB
NSDictionary* views = @ @"view": _masterViewController.view ;
NSArray* constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"|[view]|"
                                                               options:0
                                                               metrics:nil
                                                                 views:views];
[_window.contentView addConstraints:constraints];
constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[view]|"
                                                      options:0
                                                      metrics:nil
                                                        views:views];
[_window.contentView addConstraints:constraints];

这些约束将保持_masterViewController.view 填充窗口的内容视图。

【讨论】:

谢谢!只是出于好奇,这只能通过代码来实现吗?我认为它不能在 IB 中完成,因为代码被用来粘合视图和超级视图。对吗? 只能在 NIB 中为已经在同一视图层次结构中(在 NIB 中)的视图设置约束。【参考方案2】:

尝试为这 2 个(选中/取消选中)按钮添加对齐中心到 Y。将其设置为 Transmit 按钮,该按钮也将有底部空间供 superview 使用。

基本上选中/取消选中按钮应该只有高度和宽度约束加上设置为传输按钮的将中心对齐到 Y 约束。检查和取消选中按钮之间也应该有一个约束(前导空格)

希望这会有所帮助。

【讨论】:

我添加了您建议的所有约束,但无济于事。

以上是关于随着窗口变小,OSX 自动布局无法重绘某些控件的主要内容,如果未能解决你的问题,请参考以下文章

qt中怎么让窗体中的控件随着窗体自动缩放

QT中控件如何随着窗口大小的改变而使它充满整个窗口空间

Java中如何设置在JFrame中控件的位置和大小

delphi 字体变小

无法显示控件使用自动布局添加到滚动视图的内容视图中

当兄弟姐妹随自动布局发生变化时,视图不会重绘