[iOS 7] Xcode 5 で始める Auto Layout 入門 #4 – 基本操作編

とりあえず Auto Layout を使ってみる

今回は実際に Auto Layout を利用して Interface Builder 上でレイアウトを作成してみたいと思います。UILabel を常にスクリーン右下に固定するという簡単なものです。

プロジェクトの作成

まず、新しい Xcode プロジェクトを作成して下さい。テンプレートは Single View Application を利用します。

コンポーネントを配置する

プロジェクトを作成したら、Main.storyboard を表示して下さい。ViewController が一つ Canvas 上に表示されていると思います。この ViewController の View 上に UILabel を一つ、右下に配置して下さい。

xcode5-autolayout01-075

この状態で実行してみましょう。デバイスのオリエンテーションがポートレイトの場合は特に問題なく表示されます。

xcode5-autolayout01-076

しかし、デバイスを回転してランドスケープにすると、UILabel はスクリーン上から消えてしまいます。

xcode5-autolayout01-077

Auto Layout 利用時に何の制約も適用されていないコンポーネントは、Canvas 上で配置した際の座標に frame が固定されます。したがって、先ほど配置した UILabel もデバイスの回転の際に座標が変わらず、ランドスケープの場合にはスクリーンの外に出てしまいました。

制約を適用する

では、UILabel が常に画面の右下に表示されるように Auto Layout の制約を設定しましょう。といっても手順はごく簡単です。

Canvas 上で UILabel を選択して Canvas 右下の Resolve Auto Layout Issues メニューボタンを押下します。すると、メニューが表示されますので、その中の Add Missing Constraints を選択します。これは、選択中のコンポーネントに対して、適当な制約を自動的に選択して追加してくれる機能です。

xcode5-autolayout01-078

Add Missing Constraints を実行すると、親ビューの右端と下端からの間隔に関する制約が追加されます。

xcode5-autolayout01-079

これで制約の追加は完了です。実行してランドスケープの際の動作を見てみましょう。UILabel が右下に表示されるようになっていることが確認できると思います。

xcode5-autolayout01-080

とても簡単ですね。

制約と Frame

制約の削除

先ほどのラベルの垂直方向の位置をスクリーンの中央に変更してみましょう。まず、垂直方向の位置に関する制約を削除します。制約の削除は、制約を選択後 delete キーを押下することで行うことができます。

xcode5-autolayout01-081

制約の追加

次に、垂直方向の位置を親ビュー内でセンタリングする制約を追加します。Canvas 上で UILabel を選択して、Canvas 右下の Align メニューボタンを押下すると、下図のメニューが表示されます。この中で Vertical Center in Container の項目を選択して、一番下の Add 1 Constraint ボタンを押下して下さい。これで、選択した Vertical Center in Container の制約が UILabel に追加されます。

xcode5-autolayout01-082

制約と Frame の矛盾

制約自体は問題なく追加されたのですが、Canvas 上の制約を表すインジケータの色が黄色になってしまいました。また、UILabel の位置も右下のままですし、制約によって 指定した位置には黄色い点線の矩形が描画されています。これは、コンポーネントの Frame で表現されるレイアウトと、制約によって表現されるレイアウトが一致していない場合に発生します。

Interface Builder でコンポーネントを操作した際、編集した座標やサイズがそのまま Frame の値として設定されます。Frame の値は、従来通り Size Inspector から確認することができます。さらに、Interface Builder で制約を追加した際には、どのような制約であれ対象のコンポーネントの Canvas 上のレイアウト、つまり Frame が更新されることはありません。このため、Frame と制約の間で矛盾が発生することがあります。制約のインジケータが黄色くなっている場合はこの状態を示しています。

xcode5-autolayout01-083

Frame を制約に合わせて変更する

この状態でアプリを実行すると、レイアウトは制約で設定した通り親ビューの中で垂直方向にセンタリングされます。しかし、このままだと後々レイアウトを編集する際に紛らわしいので、コンポーネントの位置を制約に一致するように修正しましょう。

UILabel を選択して Canvas から Resolve Auto Layout Issues メニューを表示して下さい。その中の Update Frames を選択します。これは、Frame と制約に矛盾がある場合に、Frame を制約に合致するように自動的に修正してくれる機能です。逆に、制約を Frame に合致するように修正したい場合は、Update Constraints を選択します。

xcode5-autolayout01-084

Update Frames を実行すると、下図のように UILabel のレイアウトが制約で表現されたものに更新されます。また、Frame も同時に更新されているのが確認できると思います。

xcode5-autolayout01-085

少しややこしい挙動ではありますが、この状態は制約の編集時に頻繁に発生します。Canvas 上のコンポーネントの表示位置はあくまで Frame に依存しているということを常に意識するようにして下さい。

Auto Layout と Frame

さて、Canvas 上のコンポーネントの位置が Frame によって定義されていることは分かりましたが、Frame の値は Interface Builder 上での編集時のみ有効なものという訳ではありません。対象コンポーネントのレイアウトを決定するのに十分な制約が設定されていない場合、もしくは対象コンポーネントに一切制約が設定されていない場合には、実行時のコンポーネントのレイアウトに Frame の値がそのまま適用されます。大事なルールなのでぜひ覚えておいて下さい。

まとめ

今回は実際に Auto Layout を利用してレイアウトを作成してみました。様々なレイアウトを試してみて、まずは Xcode 5 での制約の編集に慣れるのがいいのではないかと思います。

次回は、もう少し込み入ったレイアウトを作成してみたいと思います。