自动布局 - 使用约束优先级的一个故事板的纵向和横向?

时间:2014-05-08 08:51:45

标签: ios objective-c autolayout

如何使用自动布局实现以下布局?

我可以使用一组约束来完成此操作,例如使用不同约束优先级?或者我是否需要将它分成两个单独的定义 - 如果是这样,我如何在它们之间无缝转换?

enter image description here

Big Box(图片)

  • 应始终以屏幕为中心,占用尽可能多的空间(减去最近边框的小填充)
  • square,ratio 1:1
  • 实际尺寸动态取决于可用的屏幕空间

小盒子(按钮)

  • 方形,比例1:1,固定尺寸(例如150×150 pt)

肖像

小方框应该在大方框下方

风景

由于垂直空间有限,小盒子应移动到右侧,同样与大盒子和边框的距离相等(但这次是右边的那个)

理想情况下,我想直接在其Storyboard中设置约束。但是,如果我需要创建单独的版本,我更喜欢代码。

2 个答案:

答案 0 :(得分:0)

我认为最好的方法是使用代码动态更新约束。我使用另一个SO用户提供的this framework

您需要覆盖updateConstraints并将当前方向存储在属性中,这样您就不会不必要地更新约束(这将导致性能问题)。在您的布局中,可能只有一个需要替换的约束;我可能会将对它的引用存储为属性,所以我不需要查找它。然后,您的updateConstraints实现只会移除该约束并将其替换为纵向/横向等效。使用框架提供的autoPinEdge:toEdge:ofView:withOffset:方法,您可以使用偏移来管理视图之间的间距。

例如:

  

self.savedConstraint = [smallView autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:largeView withOffset:kSpacing];

在你的情况下,我认为你只需要替换将小视图的上边缘固定到较大视图的底部(纵向)的约束,并将其替换为将小视图的前边缘固定到的视图。小的后缘。您可能还需要从小视图的底部/尾部边缘到超级视图的底部/右边缘管理约束。

答案 1 :(得分:0)

您需要通过代码来完成。在视图控制器中:

- (void)viewDidLoad
{

    //Set width and height of big box
    [bigBox addConstraint:[NSLayoutConstraint constraintWithItem:bigBox
                                                       attribute:NSLayoutAttributeWidth
                                                       relatedBy:NSLayoutRelationEqual
                                                          toItem:nil
                                                       attribute:NSLayoutAttributeNotAnAttribute
                                                      multiplier:1.0
                                                        constant:BIG_BOX_WIDTH]];

    [bigBox addConstraint:[NSLayoutConstraint constraintWithItem:bigBox
                                                       attribute:NSLayoutAttributeHeight
                                                       relatedBy:NSLayoutRelationEqual
                                                          toItem:nil
                                                       attribute:NSLayoutAttributeNotAnAttribute
                                                      multiplier:1 constant:BIG_BOX_HEIGHT]];

    //Center big box in super view
    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:bigBox
                                                          attribute:NSLayoutAttributeCenterX
                                                          relatedBy:NSLayoutRelationEqual
                                                             toItem:self.view
                                                          attribute:NSLayoutAttributeCenterX
                                                         multiplier:1.0 constant:0]];

    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:bigBox
                                                          attribute:NSLayoutAttributeCenterX
                                                          relatedBy:NSLayoutRelationEqual
                                                             toItem:self.view
                                                          attribute:NSLayoutAttributeCenterX
                                                         multiplier:1.0 constant:0]];

    //Set width and height of small box
    [smallBox addConstraint:[NSLayoutConstraint constraintWithItem:smallBox
                                                       attribute:NSLayoutAttributeWidth
                                                       relatedBy:NSLayoutRelationEqual
                                                          toItem:nil
                                                       attribute:NSLayoutAttributeNotAnAttribute
                                                      multiplier:1.0
                                                        constant:SMALL_BOX_WIDTH]];

    [smallBox addConstraint:[NSLayoutConstraint constraintWithItem:smallBox
                                                       attribute:NSLayoutAttributeHeight
                                                       relatedBy:NSLayoutRelationEqual
                                                          toItem:nil
                                                       attribute:NSLayoutAttributeNotAnAttribute
                                                      multiplier:1 constant:SMALL_BOX_HEIGHT]];


}

- (void) willAnimateRotationToInterfaceOrientation (UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
    [UIView animateWithDuration:duration animations:^{
        [self updateViewConstraints];
        [self.view layoutIfNeeded];
    }];
}

- (void)updateViewConstraints
{


    //Remove previous position constraints between big box and small box.
    for(NSLayoutConstraint *boxPosition in self.boxPositionConstraints) {
        [self.view removeConstraint:boxPosition];
    }
    self.boxPositionConstraints = nil;

    //Check orientation and create new visual format layout between big box and small box
    BOOL layoutIsPortrait = UIDeviceOrientationIsPortrait(self.interfaceOrientation);
    NSString *axisPrefix = layoutIsPortrait ? @"V" : @"H:";
    NSLayoutFormatOptions alignmentOption = layoutIsPortrait ? NSLayoutFormatAlignAllCenterX : NSLayoutFormatAlignAllCenterY;
    NSString *layoutFormat = [NSString stringWithFormat:@"%@:[bigBox]-%@-[smallBox]", axisPrefix, BOX_DISTANCES];

    NSDictionary *bindings = NSDictionaryOfVariableBindings(bigBox, smallBox);
    self.boxPositionConstraints = [NSLayoutConstraint constraintsWithVisualFormat:layoutFormat
                                                                              options:alignmentOption
                                                                              metrics:nil
                                                                                views:bindings];
    [self.view addConstraints:self.boxPositionConstraints];

}

从你的图表中,我假设你的大盒子的大小取决于设备的宽度。如果是这样,您可以根据所使用的设备创建正确大小的条件。由于只有少数iOS设备,我现在假设现在比使用大小取决于屏幕尺寸更容易。