Autolayoutは便利。
特にInterfaceBuilderで設定する場合は。
コード側で設定する時も、あの文法さえ理解すればそんなに難しくはない。
最初はとっつきにくく感じるけど、結局は慣れの問題。何だってそうか。
でも、デバイスの縦と横とでレイアウトを大幅に変更したい時は少々、手を加える必要がある。
親のviewに対して絶対座標で常に指定できるのであれば、
デバイスの向きに関わらず値を調整するだけで済むけれど
各UIの要素に対して相対的な位置で並べる時はそうもいかない。
例えば、こんなレイアウト。
縦と横とで画像とlabelの位置関係が異なるため、Autolayoutも縦用と横用とを用意する必要がある。
その処理はUIViewControllerの - (void)updateViewConstraints の中に書く。
以下コード(label2の文字列が1行で収まらないことも考慮)。
- (void)updateViewConstraints { [super updateViewConstraints]; // remove first [self.view removeConstraints:self.view.constraints]; if (UIInterfaceOrientationIsLandscape(self.interfaceOrientation)) { // for landscape [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-25-[_label1(21)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_label1)]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-15-[_label1]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_label1)]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[_label1]-10-[_imageView(240)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_label1, _imageView)]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-15-[_imageView(240)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_label1, _imageView)]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[_imageView]-15-[_label2(220)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_label2, _imageView)]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[_label1]-10-[_label2(<=150)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_label2, _label1)]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[_imageView]-15-[_label3]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_label3, _imageView)]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[_label2]-15-[_label3(21)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_label2, _label3)]]; } else { // for portrait [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-30-[_label1(21)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_label1)]]; [self.view addConstraint:[NSLayoutConstraint constraintWithItem:_label1 attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[_label1]-15-[_imageView(240)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_label1, _imageView)]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[_imageView(240)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_imageView)]]; [self.view addConstraint:[NSLayoutConstraint constraintWithItem:_imageView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[_imageView]-15-[_label2(<=150)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_label2, _imageView)]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[_label2(290)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_label2)]]; [self.view addConstraint:[NSLayoutConstraint constraintWithItem:_label2 attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[_label2]-15-[_label3(21)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_label2, _label3)]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[_label3(290)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_label3)]]; [self.view addConstraint:[NSLayoutConstraint constraintWithItem:_label3 attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0]]; } }
これで縦と横とでちゃんとレイアウトが保たれる。
旧来通りの矩形計算と比べ、手間的にはそんなに変わらない気もするけれど
文字列の長さを計算したりする必要がないので、楽になったことには違いない。
堕落プログラマにはなれないものの、ものぐさプログラマにはなれる、
Autolayoutとはそんな機能、かもしれなかった。