ios自动布局视觉格式设置子视图与父视图大小相同,但垂直偏移

Posted

技术标签:

【中文标题】ios自动布局视觉格式设置子视图与父视图大小相同,但垂直偏移【英文标题】:ios autolayout visual format to set a subview the same size as parent view, but offset vertically 【发布时间】:2013-08-20 13:19:16 【问题描述】:

我正在寻找实现上拉菜单样式的界面。我希望菜单的大小与父视图相同,但最初定位为只有其顶部 65 个像素可见。轻按菜单将使其从底部开始覆盖大部分屏幕的屏幕动画。在不是实际菜单选项的任何地方进一步点击菜单会将其放回原来的位置。

我设法在没有限制的情况下实现了这一点,但出于好奇,我想我会尝试在有限制的情况下实现相同的目标(希望减少我在各种设备尺寸等上处理旋转的代码量)。

谁能告诉我视觉格式字符串与父级匹配大小,但将顶部链接到父级底部上方 65 像素?

此外,当我触摸菜单时,我将如何为帧位置的变化设置动画?

【问题讨论】:

【参考方案1】:

我可能会建议两种方法:

    与其将其设置为全尺寸并在很大程度上远离屏幕,不如将其设置为 65 像素并限制在底部:

    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[menuview]|" options:0 metrics:nil views:views]];
    self.verticalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[menuview(65)]|" options:0 metrics:nil views:views];
    [self.view addConstraints:self.verticalConstraints];
    

    这样,当你改变方向时,它会一直固定在底部,高度为 65 点。

    然后,当您想将其设置为动画时,您可以:

    [self.view removeConstraints:self.verticalConstraints];
    self.verticalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[menuview]|" options:0 metrics:nil views:views];
    [self.view addConstraints:self.verticalConstraints];
    [UIView animateWithDuration:0.25 animations:^
        [self.view layoutIfNeeded];
    ];
    

    另一种方法,使其全尺寸和大部分离屏要求您至少使用一个非 VFL 约束。同样,您定义了初始约束,这次将其定义为主视图(其父视图)的高度,但菜单的顶部约束是距 bottom 约束的 -65 点它的超级视图(这是在 VFL 中无法完成的最后一个约束)。注意,因为我想引用 VFL 中的超级视图(定义高度相等),所以我将使用一个临时变量,mainview

    UIView *mainview = self.view;
    NSDictionary *views = NSDictionaryOfVariableBindings(menuview, mainview);
    [mainview addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[menuview]|" options:0 metrics:nil views:views]];
    [mainview addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[menuview(==mainview)]" options:0 metrics:nil views:views]];
    self.verticalConstraint = [NSLayoutConstraint constraintWithItem:menuview attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:mainview attribute:NSLayoutAttributeBottom multiplier:1.0 constant:-65.0];
    [mainview addConstraint:self.verticalConstraint];
    

    然后,当您想要将其设置为动画时,您可以摆脱垂直约束,并创建一个新的,将菜单视图的顶部约束到其父视图的顶部:

    [mainview removeConstraint:self.verticalConstraint];
    self.verticalConstraint = [NSLayoutConstraint constraintWithItem:menuview attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:mainview attribute:NSLayoutAttributeTop multiplier:1.0 constant:0.0];
    [mainview addConstraint:self.verticalConstraint];
    [UIView animateWithDuration:0.25 animations:^
        [mainview layoutIfNeeded];
    ];
    

其他技术(例如将顶部约束设置为等于视图高度减去 65 点)需要您在旋转事件期间进行调解。上述两种技术不需要。

【讨论】:

这看起来是一个很好的解决方案(没有特别附加到 visualFormat 所以可能会选择数字 2)【参考方案2】:

这里是Apple's documentation on expressing constraints。

您需要两个重要的垂直约束。首先是子视图的高度应该等于父视图的高度。二是子视图的顶部应该与父视图的底部有一定的距离。

如果您跟踪属性中的第二个约束,动画将变得非常容易。您可以将约束替换为另一个约束或编辑其constant 属性,以便子视图的顶部与父视图的顶部对齐。如果你把它放在一个动画块中并跟随它

[parent layoutIfNeeded];

约束更改将动画化。

希望这会有所帮助!

【讨论】:

以上是关于ios自动布局视觉格式设置子视图与父视图大小相同,但垂直偏移的主要内容,如果未能解决你的问题,请参考以下文章

使用自动布局调整子视图的大小

调整子视图大小的自动布局问题

iOS中的自动布局问题

在 IB 中,当我调整父视图的大小时,如何让子视图保持与父视图相同的大小?

根据子视图调整超级视图的大小

iOS 故事板 - 自动布局不会调整子视图的大小和位置