使用 AutoLayout 约束隐藏 UIView
Hiding a UIView using AutoLayout constraints
有时我想从布局中删除一个子视图。它不仅应该被隐藏,而且不应该被认为是视图 'flow' 的一部分,可以这么说。一个例子:
我正在寻找一种以编程方式隐藏橙色视图的策略。盒子的布局及其内容是通过自动布局实现的。需要注意两点:
- 橙色框根据内容定义其垂直高度,外加一些 top/bottom 边距偏移。因此,将标签的文本设置为 nil 只会 'shrink' 视图缩小到它的内部边距,它不会有 0 的高度。
- 同样,三个盒子之间的垂直间距意味着即使橙色盒子的高度为0,红色和黄色之间的间距也会是所需的两倍。
可能的解决方案
我最好的建议是向橙色框添加约束,将其高度设置为 0。为此,我需要对橙色框内的所有垂直约束使用非必需的优先级。同时,容器应该更新分隔框的约束常量。我不太喜欢这种方法,因为橙色框 class 正在定义它的内部约束,同时考虑到它的超级视图的行为。如果橙色框视图改为公开添加 0 高度约束本身的 'collapse' 方法,也许我可以接受它。
有没有更好的方法?
您可以做的是将橙色视图的高度限制作为出口(以便能够访问它)。
然后像这样为折叠设置动画:
[UIView animateWithDuration:0.3 animations:^{
orangeHeightConstraint.constant = 0;
[self.view layoutIfNeeded]
}];
橙色视图必须对红色视图有一个顶部约束,对黄色视图有一个底部约束。
还要确保以编程方式检查 IB 或 [orangeView clipsToBounds]
中的 Clip Subviews
我会通过将子视图的所有 "necessary" space 作为子视图本身的一部分来解决这个问题。这条路,
1. Red View Height = 可见红色部分+底部space
2.橙色视图高度=可见橙色部分+底部space
3.黄色View Height = 可见黄色+底部space
当您通过 Autolayout 将 Orange View Height 设置为 0 时,它也会自动将底部 space 缩小为 0。
您可以通过在较低优先级的黄色和红色视图之间添加额外约束并在代码中调整优先级来实现。
短虚线约束(orangeToRedCon 是出口)的优先级为 999(您不能将必需的优先级更改为非必需的,因此它不是 1000)。长虚线约束 (yellowToRedCon) 的优先级为 500,常量为 20。在代码中,您可以隐藏橙色视图,并交换这些优先级,这将导致黄色视图向上移动到您设置的任何值设置为 yellowToRedCon 的常量值。
-(void)changePriorities {
self.yellowToRedCon.priority = 999;
self.orangeToRedCon.priority = 500;
[UIView animateWithDuration:.5 animations:^{
self.orangeView.alpha = 0;
[self.view layoutIfNeeded];
}];
}
此方法不需要更改橙色视图的高度。
在 iOS 9 中,您可以使用 UIStackView
。
还有用于旧版本的 polyfill:TZStackView and OAStackView
有时我想从布局中删除一个子视图。它不仅应该被隐藏,而且不应该被认为是视图 'flow' 的一部分,可以这么说。一个例子:
我正在寻找一种以编程方式隐藏橙色视图的策略。盒子的布局及其内容是通过自动布局实现的。需要注意两点:
- 橙色框根据内容定义其垂直高度,外加一些 top/bottom 边距偏移。因此,将标签的文本设置为 nil 只会 'shrink' 视图缩小到它的内部边距,它不会有 0 的高度。
- 同样,三个盒子之间的垂直间距意味着即使橙色盒子的高度为0,红色和黄色之间的间距也会是所需的两倍。
可能的解决方案
我最好的建议是向橙色框添加约束,将其高度设置为 0。为此,我需要对橙色框内的所有垂直约束使用非必需的优先级。同时,容器应该更新分隔框的约束常量。我不太喜欢这种方法,因为橙色框 class 正在定义它的内部约束,同时考虑到它的超级视图的行为。如果橙色框视图改为公开添加 0 高度约束本身的 'collapse' 方法,也许我可以接受它。
有没有更好的方法?
您可以做的是将橙色视图的高度限制作为出口(以便能够访问它)。 然后像这样为折叠设置动画:
[UIView animateWithDuration:0.3 animations:^{
orangeHeightConstraint.constant = 0;
[self.view layoutIfNeeded]
}];
橙色视图必须对红色视图有一个顶部约束,对黄色视图有一个底部约束。
还要确保以编程方式检查 IB 或 [orangeView clipsToBounds]
中的 Clip Subviews
我会通过将子视图的所有 "necessary" space 作为子视图本身的一部分来解决这个问题。这条路, 1. Red View Height = 可见红色部分+底部space 2.橙色视图高度=可见橙色部分+底部space 3.黄色View Height = 可见黄色+底部space
当您通过 Autolayout 将 Orange View Height 设置为 0 时,它也会自动将底部 space 缩小为 0。
您可以通过在较低优先级的黄色和红色视图之间添加额外约束并在代码中调整优先级来实现。
短虚线约束(orangeToRedCon 是出口)的优先级为 999(您不能将必需的优先级更改为非必需的,因此它不是 1000)。长虚线约束 (yellowToRedCon) 的优先级为 500,常量为 20。在代码中,您可以隐藏橙色视图,并交换这些优先级,这将导致黄色视图向上移动到您设置的任何值设置为 yellowToRedCon 的常量值。
-(void)changePriorities {
self.yellowToRedCon.priority = 999;
self.orangeToRedCon.priority = 500;
[UIView animateWithDuration:.5 animations:^{
self.orangeView.alpha = 0;
[self.view layoutIfNeeded];
}];
}
此方法不需要更改橙色视图的高度。
在 iOS 9 中,您可以使用 UIStackView
。
还有用于旧版本的 polyfill:TZStackView and OAStackView