ios autolayout可视格式设置子视图与父视图大小相同,但垂直偏移

时间:2013-08-20 13:19:16

标签: ios uiviewcontroller uiinterfaceorientation nsautolayout

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

我设法在没有约束的情况下实现了这一点,但出于好奇,我认为我会尝试用约束来实现同样的事情(希望减少我在各种设备大小上处理轮换的代码量等)。

任何人都可以告诉我视觉格式字符串与父母的尺寸相匹配,但是将顶部链接到父母底部上方65像素?

那么当我触摸菜单时,如何设置帧位置变化的动画?

2 个答案:

答案 0 :(得分:4)

我可能会建议两种方法:

  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];
    }];
    
  2. 另一种方法是使其全尺寸并且大部分在屏幕外,需要使用至少一个非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];
    }];
    
  3. 其他技术(例如将顶部约束设置为等于视图的高度减去65点)需要您在旋转事件期间进行调解。以上两种技术不需要。

答案 1 :(得分:1)

这是Apple's documentation on expressing constraints

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

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

跟着它
[parent layoutIfNeeded];

约束更改将设置动画。

希望这有帮助!