AutoLayout 以编程方式不起作用
AutoLayout programmatically doesn't work
我想深入了解自动布局,所以我想以编程方式进行,以便理解它 properly.I 知道如何通过故事板漂亮地使用它 well.Now 这就是我正在做(在 viewDidAppear:
)
-(void)scenario2{
PGView *viewA = [[PGView alloc]initWithFrame:CGRectMake(100, 100, 100, 100) andBackgroundColor:[UIColor blackColor]];
[self.view addSubview:viewA];
PGView *viewB = [[PGView alloc]initWithFrame:CGRectMake(200, 300, 100, 100) andBackgroundColor:[UIColor yellowColor]];
[self.view addSubview:viewB];
viewA.translatesAutoresizingMaskIntoConstraints = NO;
viewB.translatesAutoresizingMaskIntoConstraints = NO;
NSLayoutConstraint *constraint;
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[viewB(==100)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(viewB)]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[viewB(==100)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(viewB)]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[viewA(==200)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(viewA)]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[viewA(==200)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(viewA)]];
//problem statement
constraint = [NSLayoutConstraint constraintWithItem:viewA attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:viewB attribute:NSLayoutAttributeWidth multiplier: 3.0f constant: 0.0f];
[self.view addConstraint:constraint];
NSLog(@"%@",viewA);
NSLog(@"%@",viewB);
}
所以这里我初始化了两个不同颜色的view
我知道我需要设置属性。 translatesAutoresizingMaskIntoConstraints
到 NO
,然后再应用任何新约束。所以我做到了。
现在我指定 views.So 的高度和宽度,两个视图的 x_position 和 y_position 都是 0.I 运行 代码,我得到了预期的结果。两个视图在 (0,0) 点都有指定的高度和宽度。
问题
现在当我写语句"problem statement"根据viewA的宽度调整viewB的宽度时,它不起作用。
此外,当我打印视图 viewA 和 viewB 时,它会将帧打印为 (0,0,0,0)。
谁能给我解释一下这种行为?
编辑:这是我所做的一些修改 made.I 使用 'hasAmbiguousLayout' 检查了两个视图的歧义及其工作正常 now.Now 如果我下一步应该做什么想要将 viewB 的宽度调整为 viewA 的宽度的三倍?
-(void)scenario2{
PGView *viewA = [PGView new];
viewA.backgroundColor = [UIColor yellowColor];
[self.view addSubview:viewA];
PGView *viewB = [PGView new];
viewB.backgroundColor = [UIColor blackColor];
[self.view addSubview:viewB];
viewA.translatesAutoresizingMaskIntoConstraints = NO;
viewB.translatesAutoresizingMaskIntoConstraints = NO;
NSLayoutConstraint *constraint;
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[viewB(==100)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(viewB)]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[viewB(==100)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(viewB)]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[viewA(==200)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(viewA)]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[viewA(==200)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(viewA)]];
NSLog(@"%d",viewA.hasAmbiguousLayout);
NSLog(@"%d",viewB.hasAmbiguousLayout);
NSLog(@"%@",viewA);
NSLog(@"%@",viewB);
}
问题是您已经明确地将 A 和 B 的宽度限制分别设置为 200 和 100。因此,当与其他约束结合使用时,指定一个宽度应为另一个宽度的三倍的附加约束无法满足。
此外,约束是不明确的,因为您已经定义了宽度和高度约束,但还没有定义 这两个框架应该在哪里。是的,您已经为这两个视图定义了 frame
,但是当您应用约束时它会被忽略。您可能根本不应该定义 frame
值,因为它具有误导性和混淆性。但是你应该设置,例如,leading 和 top 约束,或者在 VFL 中指定它们,或者添加 centerX
和 centerY
约束。您只需要一些约束来指定视图的放置位置,并且有很多方法可以指定它。
最后您没有看到合理的 frame
值的原因是您已经定义了约束,但尚未应用它们。如果需要,您可以在 viewDidLayoutSubviews
中检查它们。
您可以这样做:
- (void)scenario2 {
PGView *viewA = [PGView new];
viewA.backgroundColor = [UIColor yellowColor];
[self.view addSubview:viewA];
PGView *viewB = [PGView new];
viewB.backgroundColor = [UIColor blackColor];
[self.view addSubview:viewB];
viewA.translatesAutoresizingMaskIntoConstraints = NO;
viewB.translatesAutoresizingMaskIntoConstraints = NO;
NSDictionary *views = NSDictionaryOfVariableBindings(viewA, viewB);
// note, I added `|-100-` to say it's 100 points from the top (and 100 tall)
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-100-[viewB(==100)]" options:0 metrics:nil views:views]];
// likewise, to say 200 points from the left (and 100 wide)
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-200-[viewB(==100)]" options:0 metrics:nil views:views]];
// again, 100 from the top (as well as 200 tall)
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-100-[viewA(==200)]" options:0 metrics:nil views:views]];
// and 100 from the left
// but I've removed width definition, as we'll use your multiplier constraint below
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-100-[viewA]" options:0 metrics:nil views:views]];
// now that we've removed the width constraint from the above,
// this should now work fine
NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:viewA attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:viewB attribute:NSLayoutAttributeWidth multiplier: 3.0f constant: 0.0f];
[self.view addConstraint:constraint];
// no point in doing this, because constraints haven't yet been applied
//
// NSLog(@"%@",viewA);
// NSLog(@"%@",viewB);
}
// if you want to see where they are, you could do that here:
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
for (UIView *view in self.view.subviews) {
NSLog(@"%@", view);
}
NSLog(@"-----");
}
我想深入了解自动布局,所以我想以编程方式进行,以便理解它 properly.I 知道如何通过故事板漂亮地使用它 well.Now 这就是我正在做(在 viewDidAppear:
)
-(void)scenario2{
PGView *viewA = [[PGView alloc]initWithFrame:CGRectMake(100, 100, 100, 100) andBackgroundColor:[UIColor blackColor]];
[self.view addSubview:viewA];
PGView *viewB = [[PGView alloc]initWithFrame:CGRectMake(200, 300, 100, 100) andBackgroundColor:[UIColor yellowColor]];
[self.view addSubview:viewB];
viewA.translatesAutoresizingMaskIntoConstraints = NO;
viewB.translatesAutoresizingMaskIntoConstraints = NO;
NSLayoutConstraint *constraint;
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[viewB(==100)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(viewB)]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[viewB(==100)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(viewB)]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[viewA(==200)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(viewA)]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[viewA(==200)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(viewA)]];
//problem statement
constraint = [NSLayoutConstraint constraintWithItem:viewA attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:viewB attribute:NSLayoutAttributeWidth multiplier: 3.0f constant: 0.0f];
[self.view addConstraint:constraint];
NSLog(@"%@",viewA);
NSLog(@"%@",viewB);
}
所以这里我初始化了两个不同颜色的view
我知道我需要设置属性。
translatesAutoresizingMaskIntoConstraints
到NO
,然后再应用任何新约束。所以我做到了。现在我指定 views.So 的高度和宽度,两个视图的 x_position 和 y_position 都是 0.I 运行 代码,我得到了预期的结果。两个视图在 (0,0) 点都有指定的高度和宽度。
问题
现在当我写语句"problem statement"根据viewA的宽度调整viewB的宽度时,它不起作用。
此外,当我打印视图 viewA 和 viewB 时,它会将帧打印为 (0,0,0,0)。
谁能给我解释一下这种行为?
编辑:这是我所做的一些修改 made.I 使用 'hasAmbiguousLayout' 检查了两个视图的歧义及其工作正常 now.Now 如果我下一步应该做什么想要将 viewB 的宽度调整为 viewA 的宽度的三倍?
-(void)scenario2{
PGView *viewA = [PGView new];
viewA.backgroundColor = [UIColor yellowColor];
[self.view addSubview:viewA];
PGView *viewB = [PGView new];
viewB.backgroundColor = [UIColor blackColor];
[self.view addSubview:viewB];
viewA.translatesAutoresizingMaskIntoConstraints = NO;
viewB.translatesAutoresizingMaskIntoConstraints = NO;
NSLayoutConstraint *constraint;
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[viewB(==100)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(viewB)]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[viewB(==100)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(viewB)]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[viewA(==200)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(viewA)]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[viewA(==200)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(viewA)]];
NSLog(@"%d",viewA.hasAmbiguousLayout);
NSLog(@"%d",viewB.hasAmbiguousLayout);
NSLog(@"%@",viewA);
NSLog(@"%@",viewB);
}
问题是您已经明确地将 A 和 B 的宽度限制分别设置为 200 和 100。因此,当与其他约束结合使用时,指定一个宽度应为另一个宽度的三倍的附加约束无法满足。
此外,约束是不明确的,因为您已经定义了宽度和高度约束,但还没有定义 这两个框架应该在哪里。是的,您已经为这两个视图定义了 frame
,但是当您应用约束时它会被忽略。您可能根本不应该定义 frame
值,因为它具有误导性和混淆性。但是你应该设置,例如,leading 和 top 约束,或者在 VFL 中指定它们,或者添加 centerX
和 centerY
约束。您只需要一些约束来指定视图的放置位置,并且有很多方法可以指定它。
最后您没有看到合理的 frame
值的原因是您已经定义了约束,但尚未应用它们。如果需要,您可以在 viewDidLayoutSubviews
中检查它们。
您可以这样做:
- (void)scenario2 {
PGView *viewA = [PGView new];
viewA.backgroundColor = [UIColor yellowColor];
[self.view addSubview:viewA];
PGView *viewB = [PGView new];
viewB.backgroundColor = [UIColor blackColor];
[self.view addSubview:viewB];
viewA.translatesAutoresizingMaskIntoConstraints = NO;
viewB.translatesAutoresizingMaskIntoConstraints = NO;
NSDictionary *views = NSDictionaryOfVariableBindings(viewA, viewB);
// note, I added `|-100-` to say it's 100 points from the top (and 100 tall)
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-100-[viewB(==100)]" options:0 metrics:nil views:views]];
// likewise, to say 200 points from the left (and 100 wide)
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-200-[viewB(==100)]" options:0 metrics:nil views:views]];
// again, 100 from the top (as well as 200 tall)
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-100-[viewA(==200)]" options:0 metrics:nil views:views]];
// and 100 from the left
// but I've removed width definition, as we'll use your multiplier constraint below
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-100-[viewA]" options:0 metrics:nil views:views]];
// now that we've removed the width constraint from the above,
// this should now work fine
NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:viewA attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:viewB attribute:NSLayoutAttributeWidth multiplier: 3.0f constant: 0.0f];
[self.view addConstraint:constraint];
// no point in doing this, because constraints haven't yet been applied
//
// NSLog(@"%@",viewA);
// NSLog(@"%@",viewB);
}
// if you want to see where they are, you could do that here:
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
for (UIView *view in self.view.subviews) {
NSLog(@"%@", view);
}
NSLog(@"-----");
}