如何使用自动布局实现以下布局?
我可以使用一组约束来完成此操作,例如使用不同约束优先级?或者我是否需要将它分成两个单独的定义 - 如果是这样,我如何在它们之间无缝转换?
Big Box(图片)
小盒子(按钮)
肖像
小方框应该在大方框下方
风景
由于垂直空间有限,小盒子应移动到右侧,同样与大盒子和边框的距离相等(但这次是右边的那个)
理想情况下,我想直接在其Storyboard中设置约束。但是,如果我需要创建单独的版本,我更喜欢代码。
答案 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设备,我现在假设现在比使用大小取决于屏幕尺寸更容易。