如何以编程方式更改显示旋转的布局约束

对于一个应用程序(iOS 7兼容),我需要在横向和纵向模式下完全不同的布局的可能性。 我看到以编程方式设置约束的唯一方法,并在旋转时更改它们。 所以我使用IB设置我的接口,然后以编程方式设置约束。

我看到了某种地方首先删除所有约束的方法,然后创build并添加新的约束,然后为父视图上的约束设置更新标志。 我想要的元素只是整个屏幕的宽度和一个在另一个之下:

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { self.landscapeConstraints = [NSMutableArray new]; self.portraitConstraints = self.view.constraints; //creation of the viewsDictionary [self.landscapeConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[segmentedControl]-|" options:0 metrics:nil views:viewsDictionary]]; [self.landscapeConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[fullText]-|" options:0 metrics:nil views:viewsDictionary]]; [self.landscapeConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[bubbleTitle]-|" options:0 metrics:nil views:viewsDictionary]]; [self.landscapeConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[bubble]-|" options:0 metrics:nil views:viewsDictionary]]; [self.landscapeConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[chartView]-|" options:0 metrics:nil views:viewsDictionary]]; [self.landscapeConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(20)-[segmentedControl]-[fullText]-[bubbleTitle]-[bubble]-[chartView]|" options:0 metrics:nil views:viewsDictionary]]; [self.view removeConstraints:self.portraitConstraints]; [self.view addConstraints:self.landscapeConstraints]; [self.view setNeedsUpdateConstraints]; } 

我的问题:这种方式是否完整正确?

我来这个问题,因为旋转之后的元素太大了。 看起来像superview的大小是不正确的旋转后。 因此,所有元素都太大了,看起来最大的元素(长文本标签)给出的宽度比屏幕大得多。 如果我在约束中设置了一个大小的元素(例如[segmentedControl(== 500)],那么这个元素的大小是可以的,所有其他元素也有这个大小。

命令

 NSLog(@"%@", [self.view performSelector:@selector(_autolayoutTrace)]); 

给我这样的所有元素:

 *UIView:0x7f9a38f36510- AMBIGUOUS LAYOUT for UIView:0x7f9a38f36510.minX{id: 9}, UIView:0x7f9a38f36510.minY{id: 12}, UIView:0x7f9a38f36510.Width{id: 15}, UIView:0x7f9a38f36510.Height{id: 17} 

任何人都可以暗示我在哪里做错了吗? 我正在为此工作数小时…

编辑

我真的不明白:看来解决scheme后,我删除所有的约束将是定义的超视图的大小也是这样的约束:

 NSDictionary *viewsDictionary = @{ @"view":self.view}; [self.landscapeConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[view(360)]" options:0 metrics:nil views:viewsDictionary]]; [self.landscapeConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[view(650)]" options:0 metrics:nil views:viewsDictionary]]; 

否则,所有视图都会崩溃,因为超级视图似乎具有零大小。 即使有了这些额外的约束,视图仍然离得太远(大约20px)!

任何人都可以解释给我? 我真的需要用当前的窗口大小手动生成约束? 我期望包含视图(这是主窗口)具有全屏幕的大小。

您可以像设置约束一样设置布局约束,但也可以使用IBOutlet引用它们,只需以编程方式更改它们(并在之后调用layoutIfNeeded )。 分析代码非常困难,而没有看到布局,但是你的日志显示约束不够精确(模棱两可)。 要知道哪个视图是哪个视图,可以单独logging视图,并为每个视图获取缺less的约束。 然后一个接一个地设置约束,使其不再含糊不清。

在您的声明中:

 @property (nonatomic, weak) IBOutlet NSLayoutConstraint *leftMarginViewXYZ; 

然后在界面生成器中右键单击约束并绘制您的ViewController的引用。 释放button时,您select正确的约束。

在你的代码中,你可以改变约束

 self.leftMarginViewXYZ.constant = 123; [self.view layoutIfNeeded];