以编程方式更改 UILabel 上的约束会破坏布局
Programmatically change constraint on a UILabel breaks layout
我有一个带有两个约束的 UILabel。我激活了一个约束,另一个我禁用了。我有一个禁用第一个约束并激活第二个约束的按钮。然后,当第二次点击时,禁用第二个约束并重新激活第一个约束。第一次点击此按钮会按预期工作。 UILabel 包括所有其他约束到它的 UILabel,移动到不同的位置。但是,当点击按钮将其移回时,布局会中断。 UILabel 移动到一个几乎与它之前所在位置相同的位置,但所有其他约束到它的 UILabel 都留在原处,不会移回其原始位置。
这是处理激活约束的函数。
- (void)tapOnce:(UIGestureRecognizer *)gesture
{
if (_constraintLabelOne.isActive) {
[_constraintLabelOne setActive:NO];
[_constraintLabelTwo setActive:YES];
} else {
[_constraintLabelTwo setActive:NO];
[_constraintLabelOne setActive:YES];
}
[self layoutIfNeeded];
}
约束看起来像这样。
_constraintLabelOne = [NSLayoutConstraint constraintWithItem:myLabel
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:topView
attribute:NSLayoutAttributeBottom
multiplier:1.0
constant:6];
_constraintLabelTwo = [NSLayoutConstraint constraintWithItem:myLabel
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:topView
attribute:NSLayoutAttributeBottom
multiplier:1.0
constant:20];
约束到 myLabel
的其他标签在第一次调用 tapOnce
后卡在第二个位置。 myLabel
约束更新后,为什么它们不回到初始位置?
我附上了一张屏幕截图,其中包含当前行为的绘图。蓝色方框代表topView
。洋红色框代表 myLabel
。第一个屏幕是在调用 tapOnce
之前。中间的屏幕是在调用 tapOnce
一次之后。右边的屏幕是在调用 tapOnce
两次之后。
我这样做的方法是将其中一个约束的 priority
设置得较低,因此它是 "optional",例如UILayoutPriorityDefaultHigh
,甚至更高,例如999.
然后您可以同时激活两个约束,所需的约束将优先。
要设置它,请为默认状态设置所需的约束,并为按钮按下状态设置可选约束。
您可以从两个约束都处于活动状态开始,然后在按下按钮时,您只需禁用(设置 constraint.active = NO
)所需的约束,另一个将优先。再次按下按钮时,您只需 re-enable 所需的约束。
我明白了。发生的事情是 UILabel 的高度不受约束,因此当第二个约束被停用并且第一个约束重新激活时,高度自动增加(见下图)。为了解决这个问题,我必须手动限制所有视图项的高度。如果有人有更好的解决方案,请 post 因为我不想手动设置每个项目的高度,因为这可能会导致布局在不同设备上中断。
更新
感谢 siburb 为 UI 元素指出 Content Hugging Priority
属性。我的问题的根源是未设置此 属性,这允许我的 UI 标签的高度扩展。解决方案是将此 属性 设置为 750 或更高的值。
[myLabel setContentHuggingPriority:750 forAxis:UILayoutConstraintAxisVertical];
我有一个带有两个约束的 UILabel。我激活了一个约束,另一个我禁用了。我有一个禁用第一个约束并激活第二个约束的按钮。然后,当第二次点击时,禁用第二个约束并重新激活第一个约束。第一次点击此按钮会按预期工作。 UILabel 包括所有其他约束到它的 UILabel,移动到不同的位置。但是,当点击按钮将其移回时,布局会中断。 UILabel 移动到一个几乎与它之前所在位置相同的位置,但所有其他约束到它的 UILabel 都留在原处,不会移回其原始位置。
这是处理激活约束的函数。
- (void)tapOnce:(UIGestureRecognizer *)gesture
{
if (_constraintLabelOne.isActive) {
[_constraintLabelOne setActive:NO];
[_constraintLabelTwo setActive:YES];
} else {
[_constraintLabelTwo setActive:NO];
[_constraintLabelOne setActive:YES];
}
[self layoutIfNeeded];
}
约束看起来像这样。
_constraintLabelOne = [NSLayoutConstraint constraintWithItem:myLabel
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:topView
attribute:NSLayoutAttributeBottom
multiplier:1.0
constant:6];
_constraintLabelTwo = [NSLayoutConstraint constraintWithItem:myLabel
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:topView
attribute:NSLayoutAttributeBottom
multiplier:1.0
constant:20];
约束到 myLabel
的其他标签在第一次调用 tapOnce
后卡在第二个位置。 myLabel
约束更新后,为什么它们不回到初始位置?
我附上了一张屏幕截图,其中包含当前行为的绘图。蓝色方框代表topView
。洋红色框代表 myLabel
。第一个屏幕是在调用 tapOnce
之前。中间的屏幕是在调用 tapOnce
一次之后。右边的屏幕是在调用 tapOnce
两次之后。
我这样做的方法是将其中一个约束的 priority
设置得较低,因此它是 "optional",例如UILayoutPriorityDefaultHigh
,甚至更高,例如999.
然后您可以同时激活两个约束,所需的约束将优先。
要设置它,请为默认状态设置所需的约束,并为按钮按下状态设置可选约束。
您可以从两个约束都处于活动状态开始,然后在按下按钮时,您只需禁用(设置 constraint.active = NO
)所需的约束,另一个将优先。再次按下按钮时,您只需 re-enable 所需的约束。
我明白了。发生的事情是 UILabel 的高度不受约束,因此当第二个约束被停用并且第一个约束重新激活时,高度自动增加(见下图)。为了解决这个问题,我必须手动限制所有视图项的高度。如果有人有更好的解决方案,请 post 因为我不想手动设置每个项目的高度,因为这可能会导致布局在不同设备上中断。
更新
感谢 siburb 为 UI 元素指出 Content Hugging Priority
属性。我的问题的根源是未设置此 属性,这允许我的 UI 标签的高度扩展。解决方案是将此 属性 设置为 750 或更高的值。
[myLabel setContentHuggingPriority:750 forAxis:UILayoutConstraintAxisVertical];