如何使用AutoLayout根据父高度调整子视图高度,而不添加/删除约束

时间:2014-03-11 14:02:28

标签: ios autolayout

我们说我的父视图包含多个子视图。 使用自动布局我想将父视图的高度约束设置为0,我希望父视图的所有子视图都具有与父视图相同的高度约束。

当我想隐藏视图及其所有子视图而不直接更改其约束(不添加/删除约束)时,这将极大地帮助我。

目前,我的问题解决方案是在隐藏父视图时将所有子视图高度约束更改为零,并在显示父视图时将所有子视图更新为其原始高度。 (我为UILabel提供了一个很好的技巧,其中行数等于0;而不是设置其高度约束,我只是更改其内容;当我想隐藏标签时,我只需将文本设置为空字符串@ "",这实际上将高度设置为0,因为没有文本。当我想显示标签时,我只是将其内容更改为我想要显示的内容。

3 个答案:

答案 0 :(得分:1)

如果我理解你的要求是正确的,我认为你只需要为每个子视图设置2个高度限制。

第一个将是一个高度约束,其中包含显示父视图时所需高度的常量,并将优先级设置为小于1000(我一直使用800,它似乎适用于我想要的是)。这是当superview的高度不为0时将应用的约束。

第二个高度约束将具有constant> = 0,并且priority为1000.这将是在superview height = 0时将应用的约束。

编辑:要获得优先级800约束的视图高度,您可以:

故事板:

使用您希望的内容设置视图。因此,对于标签,设置行数,字体大小等,放入一些文本(它不一定是用户将看到的文本 - 您的代码可能会在某处改变myLabel.text设置标签后,单击窗口右下角的“Pin”约束按钮,自动填充高度。应用约束,然后在创建约束后编辑约束以降低优先级

代码:

设置标签的字体,行数以及Storyboard方法中的所有其他内容,并再次添加一些虚拟文本。然后,您可以通过调用[myLabel sizeThatFits:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)].height

询问标签要显示您给出的虚拟文本的高度。

编辑2:

好的,这与我以前有点不同。我们来试试一些截图和代码snipets。这些只是我组建的快速测试项目,但您应该能够将想法扩展到您正在进行的工作。

在故事板中,为超级视图(绿色背景)和超级视图顶部的位置设置水平约束。

enter image description here

然后,为展开的高度添加高度约束。将此约束的优先级设置为High(750)。

enter image description here

然后,将您的子视图添加到超级视图。为子视图添加约束,好像一切都正常,并且超级视图不会发生任何事情。唯一的区别是您希望默认情况下将.hidden设置为YES(否则,如果视图开始折叠,则子视图将可见,并且间距将非常时髦)。请注意,对于多行标签,我没有指定高度约束 - XCode会根据我放入的文本自行计算出来。

enter image description here

最后,向superview添加第二个高度约束,constant = 0,优先级为1000.

enter image description here

现在的一点代码:

在视图控制器的.h文件中,为superview和视图的height = 0约束设置IBOutlet

MyViewController.h

#import <UIKit/UIKit.h>

@interface MyViewController : UIViewController
{
    IBOutlet NSLayoutConstraint *superHeighConstraint;
    IBOutlet UIView *myCollapsibleView;
}

@end

为了测试,我添加了一个UISegmentedControl,如果超级视图被折叠,它将切换。以下是响应选择更改的代码:

MyViewController.m

...

- (IBAction)segmentUpdated:(UISegmentedControl *)sender
{
    if ([sender selectedSegmentIndex] == 0)
    {
        [myCollapsibleView removeConstraint:superHeighConstraint];
        for (UIView *subview in [myCollapsibleView subviews])
        {
            [subview setHidden:NO];
        }
    }
    else if ([sender selectedSegmentIndex] == 1)
    {
        [myCollapsibleView addConstraint:superHeighConstraint];
        for (UIView *subview in [myCollapsibleView subviews])
        {
            [subview setHidden:YES];
        }
    }
}

使用此设置,您永远不会更改代码中的任何约束 - 您只是选择何时应用或不应用superview的height = 0约束。循环遍历[myCollapsibleView subviews]可以根据需要轻松显示/隐藏子视图,并且动态完成,因此如果您稍后添加或删除子视图,则无需触摸代码。

模拟器图片:

负载: enter image description here

切换显示: enter image description here

切换隐藏: enter image description here

答案 1 :(得分:0)

稍微不同的方法可能只是使用setHidden:来使事物出现并根据需要消失。这比以编程方式使用约束更容易实现,但有时会在奇怪的地方导致丑陋的空格。我不确定它是否适用于您的特定布局,但我认为值得一提。

答案 2 :(得分:0)

这里的解决方案很好: Hide autolayout UIView : How to get existing NSLayoutConstraint to update this one

使用类别更新已创建的约束。