ios 使用 AutoLayout 约束隐藏 UIView

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28301595/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 04:39:27  来源:igfitidea点击:

Hiding a UIView using AutoLayout constraints

iosuiviewautolayoutnslayoutconstraint

提问by Ben Packard

From time to time I have a subview that I would like to remove from a layout. Not only should it be hidden, but it should not be considered part of the view's 'flow', so to speak. An example:

有时我想从布局中删除一个子视图。它不仅应该被隐藏,而且不应该被视为视图“流程”的一部分,可以这么说。一个例子:

enter image description here

在此处输入图片说明

I am looking for a strategy to hide the orange view programmatically. The layout of the boxes, and their content, is via autolayout. Two things to note:

我正在寻找一种以编程方式隐藏橙色视图的策略。框的布局及其内容是通过自动布局进行的。有两点需要注意:

  • the orange box is defining its vertical height based on the content, plus some top/bottom offsets for margins. So, setting the labels' text to nil will only 'shrink' the view down to it's internal margins, it won't have a height of 0.
  • Similarly, the vertical spacing between the three boxes mean that even if the orange box's height is 0, the gap between red and yellow will be twice as large as required.
  • 橙色框根据内容定义其垂直高度,加上一些用于边距的顶部/底部偏移量。因此,将标签的文本设置为 nil 只会将视图“缩小”到它的内部边距,它的高度不会为 0。
  • 同样,三个框之间的垂直间距意味着,即使橙色框的高度为 0,红色和黄色之间的间隙也将是所需的两倍。

A possible solution

一个可能的解决方案

My best suggestion is to add a constraint to the orange box, setting it's height to 0. For this to work, I need to use non-required priorities for all of the vertical constraints inside the orange box. At the same time, the container should update the constant for the constraint that separates the boxes. I don't like this approach so much since the orange box class is defining it's internal constraints with it's superview's behavior in mind. Perhaps I could live with it if the orange box view instead exposes a 'collapse' method that adds the 0 height constraint itself.

我最好的建议是向橙色框添加一个约束,将其高度设置为 0。为此,我需要对橙色框内的所有垂直约束使用非必需的优先级。同时,容器应更新分隔框的约束的常量。我不太喜欢这种方法,因为橙色框类正在定义它的内部约束,并考虑到它的超级视图的行为。如果橙色框视图公开了一个添加 0 高度约束本身的“折叠”方法,也许我可以接受它。

Is there a better approach?

有没有更好的方法?

回答by rdelmar

You can do this by adding an extra constraint between the yellow and red views of a lower priority, and adjusting the priorities in code.

您可以通过在较低优先级的黄色和红色视图之间添加额外约束并在代码中调整优先级来实现此目的。

enter image description here

在此处输入图片说明

The short dashed constraint (orangeToRedCon is the outlet) has a priority of 999 (you can't change a required priority to a non-required, so that's why it's not 1000). The long dashed constraint (yellowToRedCon) has a priority of 500 and a constant of 20. In code, you can hide the orange view, and swap those priority levels, and that will cause the yellow view to move up to whatever value you've set for the constant value of yellowToRedCon.

短虚线约束(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];
    }];
}

This method doesn't require any changes in the orange view's height.

此方法不需要更改橙色视图的高度。

回答by fabb

In iOS 9 you can use UIStackViewfor this. There also are polyfills for older versions: TZStackViewand OAStackView

在 iOS 9 中,您可以使用UIStackView此功能。还有一些旧版本的polyfillTZStackViewOAStackView

回答by Jad Feitrouni

What you could do is have the height constraint of the orange view as an outlet (to be able to access it). then animate the collapse like so:

您可以做的是将橙色视图的高度约束作为出口(以便能够访问它)。然后像这样为折叠设置动画:

[UIView animateWithDuration:0.3 animations:^{
    orangeHeightConstraint.constant = 0;
    [self.view layoutIfNeeded]
}];

The orange view will have to have a top constraint to the red view and a bottom constraint to the yellow view. Also make sure to check Clip Subviews in IB or [orangeView clipsToBounds]programatically

橙色视图必须具有红色视图的顶部约束和黄色视图的底部约束。还要确保在 IB 中或以[orangeView clipsToBounds]编程方式检查 Clip Subviews

回答by Vinod Vishwanath

I would solve this by including all "necessary" spaces of a subview as part of the subview itself. This way, 1. Red View Height = visible red part + bottom space 2. Orange View Height = visible orange part + bottom space 3. Yellow View Height = visible yellow + bottom space

我会通过将子视图的所有“必要”空间作为子视图本身的一部分来解决这个问题。这样, 1. 红色视图高度 = 可见红色部分 + 底部空间 2. 橙色视图高度 = 可见橙色部分 + 底部空间 3. 黄色视图高度 = 可见黄色 + 底部空间

When you set the Orange View Height to 0 by Autolayout, it will automatically shrink the bottom space to 0 as well.

当您通过 Autolayout 将 Orange View Height 设置为 0 时,它也会自动将底部空间缩小为 0。