[iOS 7] Xcode 5 で始める Auto Layout 入門 #5 – 実践編
Auto Layout で少し込み入ったレイアウトを作成する
今回は、前回より少し込み入ったレイアウトを作成してみたいと思います。今回作成するのは、下図のような3つの UIView から構成されるレイアウトです。
下側の2つの UIView はスクリーンサイズに合わせて幅が等分され、スクリーンの高さが変わっても高さが変わりません。デバイスを横向きにした際には下図のようになります。
コンポーネントを配置する
では、Xcode で新しいプロジェクトを作成してください。テンプレートは Single View Application を利用します。
Main.storyboard を表示して、Canvas 内の ViewController 上に UIView を下図のように配置してください。配置の際は、ガイドラインに沿って配置します。わかりやすいように UIView には背景色を設定しています。
サイズに関する制約を設定する
では、下側2つの UIView にサイズに関する制約を設定したいと思います。まず、左下の UIView に高さの制約を追加します。左下の UIView を選択して Canvas 右下の Pin メニューボタンを押下すると、下図のメニューが表示されます。この中で、Height の項目を選択して、一番下の Add 1 Constraint ボタンを押下して下さい。これで、選択した Height の制約が左下の UIView に適用されます。
Document Outline 上でも制約が追加されたことが確認できます。
サイズの連動に関する制約を設定する
続いて、下側2つの UIView に幅と高さが等しくなる制約を追加します。下側2つの UIView を選択して Pin メニューを表示します。この中で、Equal Widths と Equal Heights の項目を選択して、制約追加ボタンを押下します。これで、下側2つの UIView に幅と高さが等しくなる制約が適用されます。
Document Outline 上でも制約が追加されたことが確認できます。
制約のバリデーション
ところで、Document Outline の右上に最初は表示されていなかった赤いアイコンが表示されるようになりました。これは、制約が不足していてレイアウトを確定できないコンポーネントが存在する場合など、何かしらの問題がある場合に表示されます。少々分かりづらいですが、このアイコンをクリックすると詳細な情報を表示する画面が表示されます。
では、赤いアイコンをクリックしてみましょう。下図のような画面が表示されます。
Missing Constraints という項目が不足している制約の情報です。この場合、下側の2つの UIView の水平・垂直方向の位置に関する制約が不足していることが分かります。
なお、この画面を表示した状態で Canvas 上のコンポーネントを選択すると、選択したコンポーネントの項目のみがハイライトされます。また逆に、Document Outline 上に表示されている情報の上にマウスカーソルを移動すると、対応する Canvas 上のコンポーネントがハイライトされます。表示されている情報がどのコンポーネントのものであるか分からなくなってしまった場合は、この方法で確認しましょう。
相対位置に関する制約を設定する
不足している制約が分かったので、制約を追加して問題を解消したいと思います。
水平方向の位置に関する制約を設定する
水平方向の位置に関して、追加する制約は以下の3つです。
- 左下の UIView の左端と親ビューの左端との間隔
- 右下の UIView の右端と親ビューの右端との間隔
- 左下の UIView の右端と右下の UIView の左端との間隔
まずは、1 と 3 の制約を追加します。
左下の UIView を選択して Pin メニューを表示します。このメニューの上側にある Spacing to nearest neighbor という項目から左右の相対位置の制約を選択します。制約を選択するには、"I" 字型の赤いアイコンをクリックします。選択すると点線が実線に変わります。
これは名前の通り、最も近くにあるコンポーネントとの間隔に関する制約を追加する機能です。今回の場合、右側の相対位置の制約は、右隣にある UIView との間隔を設定します。左側の相対位置の制約は、左隣にコンポーネントが存在しないため、親ビューの境界との間隔を設定することになります。
同じように、2 の制約も追加します。右下の UIView を選択して、親ビューの右端からの間隔に関する制約を追加します。
Document Outline 上から追加された制約を確認しましょう。
また、制約の問題を表示すると、水平方向の位置に関する問題がなくなったことが確認できます。
垂直方向の位置に関する制約を設定する
垂直方向に関して、以下の制約を追加します。
- 左下の UIView の下端と親ビューの下端との間隔
左下の UIView を選択して Pin メニューを表示します。Spacing to nearest neighbor で下側の相対位置の制約を選択して適用します。
Document Outline 上から追加された制約を確認しましょう。
また、制約の問題を表示すると、左下の UIView の垂直方向の位置に関する問題がなくなったことが確認できます。
アライメントに関する制約を設定する
右下の UIView に関しても左下の UIView 同様に垂直位置に関する制約を追加する必要があります。左下の UIView 同様に親ビューの下端との間隔の制約を追加してもいいのですが、ここでは、アライメントに関する制約を設定することで垂直位置を決定してみたいと思います。
具体的には以下の制約を追加します。
- 左下の UIView の下端と右下の UIView の下端の垂直位置を揃える
左下と右下の UIView を選択して Align メニューを表示します。このメニューの中にある Bottom Edges を選択して適用します。これで下端位置を揃える制約が追加されました。
Document Outline 上から追加された制約を確認しましょう。
また、全ての制約の問題が解消されたので、Document Outline の右上に赤いアイコンが表示されなくなりました。
制約の問題の表示条件
制約の問題が全て解消されたので、実際に動作を確認してみましょう。デバイスがポートレイトの場合は特に問題なく表示されているかと思います。ただし、デバイスを回転してランドスケープにした際に、下のように上側の UIView のレイアウトが崩れてしまいます。
確かに制約の問題は全て解消されていますが、まだ上側の UIView には何も制約を設定していないので、これは当然のことです。
制約の問題は、既に何らかの制約が紐づいているコンポーネントに対して、レイアウトを決定する上で不足している制約がある場合にユーザーに注意を促してくれます。しかし、全てのコンポーネントに対して制約が適用されていることを保証するものではないので注意が必要です。
残りの制約を設定する
では、上側の UIView に対して制約を追加しましょう。ここで追加する制約は下記の通りです。
- 上側の UIView の上端と親ビューの上端との間隔
- 上側の UIView の左端と親ビューの左端との間隔
- 上側の UIView の右端と親ビューの右端との間隔
- 上側の UIView の下端と左下の UIView の上端との間隔
上側の UIView を選択して Pin メニューを表示します。Spacing to nearest neighbor で上下左右の相対位置の制約を選択して適用します。上下左右の相対位置を決定することで、親ビューや周辺のコンポーネントのサイズや位置によって自身のサイズが柔軟に変化するレイアウトになりました。
Document Outline 上から追加された制約を確認しましょう。
作成したレイアウトを確認する
さて、今度こそ全ての制約を設定したので、実際に動作を確認してみましょう。デバイスがランドスケープの場合にも、スクリーンサイズに合わせてきちんとレイアウトが変化していることが確認できます。
また、3.5 inch スクリーンで実行した場合も、下側の UIView の高さは変わらず、上側の UIView の高さが縮小することで、スクリーンサイズの違いを吸収しています。
まとめ
Interface Builder から利用できる Auto Layout の機能には実は制限があるのですが、それでも Auto Layout を利用することで、ある程度込み入ったレイアウトでも表現することが可能であることを感じて頂けたかと思います。また、Xcode 5 になって制約の編集がとても楽になったので、そのパワーを引き出しやすくなりました。
次回は、ここまでの回で説明できなかった補足事項についてまとめたいと思います。