我有一个包含三个子视图的视图。这些子视图应缩放以填充视图的整个宽度。
我尝试过使用此约束:
NSLayoutConstraint *leftConstraint = [NSLayoutConstraint constraintWithItem:smallView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:containerView attribute:NSLayoutAttributeWidth multiplier:((1 / 3) * idx) constant:0.0];
这会导致异常:
+ [NSLayoutConstraint constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant:]: 乘数0或零秒项以及位置 第一个属性创建位置相等的非法约束 一个常数。必须成对指定位置属性'
我理解它在抱怨什么但似乎令人费解,我无法得到这种行为。我希望我的第一个视图的x原点为0。
还有另一种方法可以让它发挥作用吗?
答案 0 :(得分:1)
NSLayoutAttributeLeft
等于宽度NSLayoutAttributeWidth
((1 / 3) * idx)
,我认为idx
是int
类型。因此表达式((1 / 3) * idx)
的计算结果为0.如果要使用浮点乘数,可以通过将三个数中的任何一个更改为浮点类型来实现,例如((1 / 3.0) * idx)
。如果您只有3个子视图进行布局,则可视格式可能是一种更简单易读的应用方式。假设您希望缩放3个子视图以填充containerView
,它们都具有相等的宽度。代码如下:
UIView *smallView0 = [UIView new];
smallView0.backgroundColor = [UIColor redColor];
smallView0.translatesAutoresizingMaskIntoConstraints = NO;
[containerView addSubview:smallView0];
UIView *smallView1 = [UIView new];
smallView1.backgroundColor = [UIColor blueColor];
smallView1.translatesAutoresizingMaskIntoConstraints = NO;
[containerView addSubview:smallView1];
UIView *smallView2 = [UIView new];
smallView2.backgroundColor = [UIColor greenColor];
smallView2.translatesAutoresizingMaskIntoConstraints = NO;
[containerView addSubview:smallView2];
NSDictionary *bindings = NSDictionaryOfVariableBindings(smallView0, smallView1, smallView2);
// Layout the three subviews to fill the `containerView`, and, make theirs widths equal.
NSArray *hConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"|[smallView0][smallView1(==smallView0)][smallView2(==smallView0)]|" options:0 metrics:nil views:bindings];
[containerView addConstraints:hConstraints];
// The constraints below are set to satisfy the vertical layout rules. You may have your own choice.
NSArray *vConstraints0 = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[smallView0]-|" options:0 metrics:nil views:bindings];
NSArray *vConstraints1 = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[smallView1]-|" options:0 metrics:nil views:bindings];
NSArray *vConstraints2 = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[smallView2]-|" options:0 metrics:nil views:bindings];
[containerView addConstraints:vConstraints0];
[containerView addConstraints:vConstraints1];
[containerView addConstraints:vConstraints2];
更一般地说,您可能有超过3个子视图或必须在运行时决定它。对于这种情况,for循环可能会有所帮助:
UIView *previousView = nil;
int countOfSubviews = 6;
for (int i = 0; i < countOfSubviews; ++i) {
UIView *smallView = [UIView new];
[containerView addSubview:smallView];
smallView.backgroundColor = (i % 2 == 0) ? [UIColor redColor] : [UIColor greenColor];
smallView.translatesAutoresizingMaskIntoConstraints = NO;
NSLayoutConstraint *fixedHeight = [NSLayoutConstraint constraintWithItem:smallView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:50];
[smallView addConstraint:fixedHeight];
if (i == 0) {
NSLayoutConstraint *left = [NSLayoutConstraint constraintWithItem:smallView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:containerView attribute:NSLayoutAttributeLeft multiplier:1 constant:0];
[containerView addConstraint:left];
} else {
NSLayoutConstraint *internal = [NSLayoutConstraint constraintWithItem:smallView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:previousView attribute:NSLayoutAttributeRight multiplier:1 constant:0];
[containerView addConstraint:internal];
}
if (i == countOfSubviews - 1) {
NSLayoutConstraint *right = [NSLayoutConstraint constraintWithItem:smallView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:containerView attribute:NSLayoutAttributeRight multiplier:1 constant:0];
[containerView addConstraint:right];
}
NSLayoutConstraint *verticalPostiion = [NSLayoutConstraint constraintWithItem:smallView attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:containerView attribute:NSLayoutAttributeCenterY multiplier:1 constant:0];
[containerView addConstraint:verticalPostiion];
if (previousView) {
NSLayoutConstraint *equalWidth = [NSLayoutConstraint constraintWithItem:smallView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:previousView attribute:NSLayoutAttributeWidth multiplier:1 constant:0];
[containerView addConstraint:equalWidth];
}
previousView = smallView;
}
答案 1 :(得分:1)
如果您的部署目标是iOS 9.0或更高版本,那么将这三个子视图放入UIStackView
可能会更简单。默认的堆栈视图设置应该按照您的需要进行:水平放置三个视图,端对端,拉伸以填充堆栈视图的宽度,中间没有填充。
答案 2 :(得分:0)
如您所知,您无法创建仅将坐标指定为常量的约束。相反,创建一个相对于某个“里程碑”的人。在这种情况下,由于您希望原点的x坐标为0,这意味着视图的左边缘将与其超视图的左边缘重合。因此,创建一个建立该关系的约束:
NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:smallView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:containerView attribute:NSLayoutAttributeLeft multiplier:1 constant:0.0];
它必须与其他两个不同,尽管实现这种分裂的通常方法是:
(请注意,我使用的是前导和尾随而不是左右。这使得您的UI会自动镜像从右到左的语言。)