我可以使用autolayout为横向和纵向方向提供不同的约束吗?

Ben*_*ard 47 cocoa-touch uiviewcontroller uiview ios autolayout

设备旋转时是否可以更改约束?怎么可能实现这一目标?

一个简单的例子可能是两个图像,它们在纵向上一个堆叠在另一个之上,但在景观中是并排的.

如果这是不可能的,我怎么可能完成这个布局?

我正在构建代码中的视图和约束,而不是使用接口构建器.

knl*_*knl 39

编辑:使用Xcode 6中引入的大小类的新概念,您可以在Interface Builder中轻松地为特定大小类设置不同的约束.大多数设备(例如所有当前的iPhone)在横向模式下都具有紧凑的垂直尺寸等级.

对于一般布局决策而言,这是一个比确定设备方向更好的概念.

话虽这么说,如果你真的需要知道方向,那UIDevice.currentDevice().orientation就是要走的路.


原帖:

覆盖为特定情况提供布局约束的updateViewConstraints方法UIViewController.这样,布局总是根据情况设置正确的方式.确保它们与故事板中创建的约束形成一组完整的约束.您可以使用IB来设置常规约束,并标记要在运行时删除的更改.

我使用以下实现为每个方向提供一组不同的约束:

-(void)updateViewConstraints {
    [super updateViewConstraints];

    // constraints for portrait orientation
    // use a property to change a constraint's constant and/or create constraints programmatically, e.g.:
    if (!self.layoutConstraintsPortrait) {
        UIView *image1 = self.image1;
        UIView *image2 = self.image2;
        self.layoutConstraintsPortrait = [[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[image1]-[image2]-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(image1, image2)] mutableCopy];
        [self.layoutConstraintsPortrait addObject:[NSLayoutConstraint constraintWithItem:image1 attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem: image1.superview attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]];
        [self.layoutConstraintsPortrait addObject:[NSLayoutConstraint constraintWithItem:image2 attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:image2.superview attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]];
    }

    // constraints for landscape orientation
    // make sure they don't conflict with and complement the existing constraints
    if (!self.layoutConstraintsLandscape) {
        UIView *image1 = self.image1;
        UIView *image2 = self.image2;
        self.layoutConstraintsLandscape = [[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[image1]-[image2]-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(image1, image2)] mutableCopy];
        [self.layoutConstraintsLandscape addObject:[NSLayoutConstraint constraintWithItem:image1 attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:image1.superview attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]];
        [self.layoutConstraintsLandscape addObject:[NSLayoutConstraint constraintWithItem:image2 attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem: image2.superview attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]];
    }

    BOOL isPortrait = UIInterfaceOrientationIsPortrait(self.interfaceOrientation);
    [self.view removeConstraints:isPortrait ? self.layoutConstraintsLandscape : self.layoutConstraintsPortrait];
    [self.view addConstraints:isPortrait ? self.layoutConstraintsPortrait : self.layoutConstraintsLandscape];        
}
Run Code Online (Sandbox Code Playgroud)

现在,您需要做的就是在情况发生变化时触发约束更新.覆盖willAnimateRotationToInterfaceOrientation:duration:方向更改的约束更新动画:

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    [super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];

    [self.view setNeedsUpdateConstraints];

}
Run Code Online (Sandbox Code Playgroud)

  • @ knl,尺寸类不能解决iPad上的肖像与风景(它们都是wRegular/hRegular). (6认同)

Tra*_*ggs 17

我使用的方法(无论好坏)是在故事板编辑器中定义两组约束(纵向和横向).

为了避免地狱的故事板警告,我将所有一组放在999的优先级,只是因为它不会显示任何地方的红色.

然后我将所有约束添加到outlet集合:

@property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *portraitConstraints;
@property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *landscapeConstraints;
Run Code Online (Sandbox Code Playgroud)

最后,我实现了我ViewControllersviewWillLayout方法:

- (void) viewWillLayoutSubviews {
    [super viewWillLayoutSubviews];
    for (NSLayoutConstraint *constraint in self.portraitConstraints) {
        constraint.active = (UIApplication.sharedApplication.statusBarOrientation == UIDeviceOrientationPortrait);
    }
    for (NSLayoutConstraint *constraint in self.landscapeConstraints) {
        constraint.active = (UIApplication.sharedApplication.statusBarOrientation != UIDeviceOrientationPortrait);
    }
}
Run Code Online (Sandbox Code Playgroud)

这似乎有效.我真的希望你能在storyboard编辑器中设置默认的活动属性.