为啥自动布局与此布局有问题

Posted

技术标签:

【中文标题】为啥自动布局与此布局有问题【英文标题】:Why does autolayout have issues with this layout为什么自动布局与此布局有问题 【发布时间】:2015-07-11 20:18:42 【问题描述】:

对于键盘扩展,我在 所有屏幕尺寸 上的 Autolayout width 遇到了一些问题。

起初它运行良好,但突然开始吐出一些错误,无论屏幕宽度如何。我没有改变任何东西,我什至尝试删除应用程序,清理项目,并从头开始布置所有内容。

这是我的布局:

| - 8 - (50) - >=8 - (130) - 8 - (130) - 8 - |
priority (50) = 750, everything else = 1000
有一个8 point space between the superview and button 1,它有一个width of 50, but a priority of 750。 然后有一个8 point or greater space between button 1 and button 2,它有一个width of 130。 然后有一个8 point space between button 2 and button 3,它也有一个width of 130。 最后是8 point space between button 3 and the superview

这不仅在 320 点4 英寸 屏幕上造成问题,而且在 375 点 4.7 英寸 屏幕和 414 点5.5 英寸 屏幕。

据我所知,项目的最大宽度为 (8+50+8+130+8+130+8) 342 点,应该没有任何问题。这比 4.7 和 5.5 英寸的屏幕都小。在 4 英寸 上,我通过打破按钮 1 上的 50 点宽度 来解决这个问题,因此总数为 320 点

在模拟器和设备上看起来都很好,但是控制台会吐出许多 Unable to simultaneously satisfy constraints 错误(准确地说是 3 个)。

这是日志:

1: (
"<NSLayoutConstraint:0x1740954a0 H:[UIButton:0x137e0cb80'Last sentence'(130)]>",
"<NSLayoutConstraint:0x1740955e0 H:[UIButton:0x137e0cda0'Pasteboard'(130)]>",
"<NSLayoutConstraint:0x174095810 H:|-(8)-[UIButton:0x137d0ba60]   (Names: '|':UIView:0x137e0c1b0 )>",
"<NSLayoutConstraint:0x1740958b0 H:[UIButton:0x137d0ba60]-(>=8)-[UIButton:0x137e0cda0'Pasteboard']>",
"<NSLayoutConstraint:0x174095950 H:[UIButton:0x137e0cda0'Pasteboard']-(8)-[UIButton:0x137e0cb80'Last sentence']>",
"<NSLayoutConstraint:0x1740959f0 H:[UIButton:0x137e0cb80'Last sentence']-(8)-|   (Names: '|':UIView:0x137e0c1b0 )>",
"<NSLayoutConstraint:0x170094ff0 'UIView-Encapsulated-Layout-Width' H:[UIView:0x137e0c1b0(55)]>"
)
Will attempt to recover by breaking constraint <NSLayoutConstraint:0x1740955e0 H:[UIButton:0x137e0cda0'Pasteboard'(130)]>

2: (
"<NSLayoutConstraint:0x1740954a0 H:[UIButton:0x137e0cb80'Last sentence'(130)]>",
"<NSLayoutConstraint:0x174095810 H:|-(8)-[UIButton:0x137d0ba60]   (Names: '|':UIView:0x137e0c1b0 )>",
"<NSLayoutConstraint:0x1740958b0 H:[UIButton:0x137d0ba60]-(>=8)-[UIButton:0x137e0cda0'Pasteboard']>",
"<NSLayoutConstraint:0x174095950 H:[UIButton:0x137e0cda0'Pasteboard']-(8)-[UIButton:0x137e0cb80'Last sentence']>",
"<NSLayoutConstraint:0x1740959f0 H:[UIButton:0x137e0cb80'Last sentence']-(8)-|   (Names: '|':UIView:0x137e0c1b0 )>",
"<NSLayoutConstraint:0x170094ff0 'UIView-Encapsulated-Layout-Width' H:[UIView:0x137e0c1b0(55)]>"
)
Will attempt to recover by breaking constraint <NSLayoutConstraint:0x1740954a0 H:[UIButton:0x137e0cb80'Last sentence'(130)]>

3: (
"<NSLayoutConstraint:0x174095810 H:|-(8)-[UIButton:0x137d0ba60]   (Names: '|':UIView:0x137e0c1b0 )>",
"<NSLayoutConstraint:0x1740958b0 H:[UIButton:0x137d0ba60]-(>=8)-[UIButton:0x137e0cda0'Pasteboard']>",
"<NSLayoutConstraint:0x174095950 H:[UIButton:0x137e0cda0'Pasteboard']-(8)-[UIButton:0x137e0cb80'Last sentence']>",
"<NSLayoutConstraint:0x1740959f0 H:[UIButton:0x137e0cb80'Last sentence']-(8)-|   (Names: '|':UIView:0x137e0c1b0 )>",
"<NSLayoutConstraint:0x170094ff0 'UIView-Encapsulated-Layout-Width' H:[UIView:0x137e0c1b0(0)]>"
)
Will attempt to recover by breaking constraint <NSLayoutConstraint:0x1740958b0 H:[UIButton:0x137d0ba60]-(>=8)-[UIButton:0x137e0cda0'Pasteboard']>

我整个晚上都在为此挠头。大家有什么建议吗?

【问题讨论】:

【参考方案1】:

无论出于何种原因,superview 至少暂时只有 55 点宽。从您引用的日志中:

"<NSLayoutConstraint:0x174095810 H:|-(8)-[UIButton:0x137d0ba60]   (Names: '|':UIView:0x137e0c1b0 )>",
...
"<NSLayoutConstraint:0x1740959f0 H:[UIButton:0x137e0cb80'Last sentence']-(8)-|   (Names: '|':UIView:0x137e0c1b0 )>",
"<NSLayoutConstraint:0x170094ff0 'UIView-Encapsulated-Layout-Width' H:[UIView:0x137e0c1b0(55)]>"

所以,|(超级视图的边缘)是UIView:0x137e0c1b0,并且被限制为 55 磅宽 (UIView:0x137e0c1b0(55))。

该视图可能由框架控制。您需要容纳它具有任意宽度(甚至为 0,如最后一个例外)。要做到这一点,请将水平间距约束之一设置为非常高但不是必需的优先级,例如 950。这样,如果可能的话,它将保持不变,但如果必须,它会被打破而不会导致异常。显而易见的选择是对 superview 后沿的约束。

超级视图比屏幕窄的情况大概是在视图层次结构被放在一起时,在它显示之前。因此,此时允许打破约束不会影响任何实际可见的布局。

【讨论】:

我可能应该提到这是一个自定义键盘扩展。您是否有任何经验认为这是一个常见问题,或者是我造成的? 对不起,我不知道。 没关系,我想我会在某个时候找到答案。不过现在,将约束的优先级降低到超级视图的后沿就可以了!谢谢!【参考方案2】:

如果我没记错的话...看起来您的“粘贴板”和“最后一个气味”按钮具有恒定的宽度和边距限制。

您对屏幕一侧的约束已经在声明宽度。因此,当自动布局运行时,它(可以理解)不知道要使用哪个约束。所以它打破了两个按钮的宽度限制,并使用其他边距限制来设置宽度。

【讨论】:

是的,两个按钮都是 130 磅宽,它们之间有 8 磅空间,“最后一句话”按钮和超级视图之间也有 8 磅空间。然而,这是必要的,因为按钮应始终为 130 宽。 “粘贴板”按钮和地球仪之间的空间应该下降,然后 50 点的地球仪按钮最终应该会损坏。然而,在大屏幕上,什么都不会中断。 我在上一篇文章中不小心按了 Enter。再次查看更新评论 我的理解是正确的,当屏幕宽度变小时,您希望两个按钮保持 130 像素的宽度,而地球则放松其宽度但最大为 50 像素? 是的,按钮应始终为 130 宽。蓝色按钮和地球仪之间的“>=8 点”空间应该向下,并最终打破“50 点”地球仪按钮 尝试将&gt;=8约束的优先级设置为750。

以上是关于为啥自动布局与此布局有问题的主要内容,如果未能解决你的问题,请参考以下文章

为啥自动布局不能产生一致的结果?

为啥这个 UIScrollView 自动布局不起作用?

为啥自动布局约束不起作用?

为啥我取消选中内容布局指南后通过了自动布局检查

当我添加自动布局约束时,为啥我的 textview 不显示?

为啥在eclipes为创建一个android布局文件在R中没有自动生成