具有常数的高度约束不是“稳定的”

Posted

技术标签:

【中文标题】具有常数的高度约束不是“稳定的”【英文标题】:Height constraint with a constant is not "stable" 【发布时间】:2013-12-04 13:26:39 【问题描述】:

我正在添加一个高度限制(设置为 300px),如下所示:

    [parentView_ addConstraints:@[
          [NSLayoutConstraint constraintWithItem:containerView_ 
                              attribute:NSLayoutAttributeHeight
                              relatedBy:NSLayoutRelationEqual
                              toItem:nil attribute:NSLayoutAttributeNotAnAttribute
                              multiplier:1.0f constant:300],
          ]];

parentView_ 有一个名为containerView_ 的子视图。

containerView_ 有两个子视图:view1view2

然后我添加按钮,一旦点击就会调用以下功能:

    [containerView_ removeConstraints:[containerView_ constraints]];
    [containerView_ addConstraints:@[
          [NSLayoutConstraint constraintWithItem:view1 
                              attribute:NSLayoutAttributeCenterY
                              relatedBy:NSLayoutRelationEqual
                              toItem:view2 attribute:NSLayoutAttributeBottom
                              multiplier:someVal1 constant:someVal2],
          ]];

someVal1someVal2 在点击之间切换(我正在控制值)。

问题:

在第一次点击期间,containerView_ 的高度从 300 变为 299(随机!),然后又回到 300 并且看起来不太好(看起来视图在增长和缩小)。

我已通过覆盖 layoutSubviews 并打印 containerView_ 的框架来验证这一点。

什么可能导致高度从 300 变为 299,即使我设置了 300(仅此而已!)的约束?

【问题讨论】:

你能发布一个展示这个问题的示例项目吗? @ArkadiuszHolko 示例项目可以在here 找到。它可能不会在第一次运行时重现,所以给它几张照片,直到你在控制台中看到“检测到错误的高度” @ArkadiuszHolko 忘了说:右边有一个蓝色的 UISlider - 尝试移动它,它会触发约束移除/添加,从而导致高度发生变化。 @ArkadiuszHolko 问题解决了 :-) 【参考方案1】:

示例项目包含已应用的约束的完整列表,其中包括:

SampleSlider.m:59

   [NSLayoutConstraint constraintWithItem:slider_ attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual
                                   toItem:self attribute:NSLayoutAttributeCenterY
                               multiplier:1.0 constant:0]

将此约束更改为

   [NSLayoutConstraint constraintWithItem:slider_ attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual
                                   toItem:self attribute:NSLayoutAttributeBottom
                               multiplier:1.0 constant:0]

解决了这个问题。它显示为 CenterY 约束不精确,或者在每次运行时将 floor()'d/ceil()'d 设置为不同的值。

我发现的有趣的事情如下:在两次不同的运行中,我打印出了框架(他的身高应该是 300):

<SampleSlider: 0x8988bd0; frame = (12 -1; 56 301); layer = <CALayer: 0x894e4b0>>
<SampleSlider: 0x894f260; frame = (12 1; 56 299); layer = <CALayer: 0x894b770>>

注意 y 位置 - 它不是稳定在 0,而是跳到 -1, 1 分别与高度 (301, 299) 一起。抛开 y 定位问题,真正令人烦恼的是框架的高度:

虽然使用了以下线性方程(或者看起来如此?),但它无论如何都不满足约束:

frameHeight = constraintHeight - y

如:

301 = 300 - (-1)

(所以实际高度是 abs(-1) + 301 = 302)

对于上面的第一帧,以及,

299 = 300 - 1

(所以实际高度是 299 - 1 = 298)

对于第二帧。 闻起来很有趣,不是吗?好像有人犯了一个错误,减去了 y 值而不是添加它。

将方程(假设意义)更改为

frameHeight = constraintHeight + y

产量

frameHeight = 300 + -1 = 299

对于第一帧,所以实际高度现在是 300(y = -1,h = 299)

frameHeight = 300 + 1 = 301

对于第二帧,所以实际高度又是 300 (y = 1, h = 301)

【讨论】:

以上是关于具有常数的高度约束不是“稳定的”的主要内容,如果未能解决你的问题,请参考以下文章

具有固定高度的表格单元格中的自动布局多行标签

多次调用估计的HeightForRowAtIndexPath 导致不稳定的uitableview

在非常量向量内的常数向量中的地址是不是稳定?

UIImageView 创建额外的宽度/高度约束

linux下oracle数据库是不是稳定

按视图高度的百分比定义恒定约束