この記事はXcode 4.6.3 & iOS 6のものです。Xcode 5 & iOS 7はこちら。
http://blogios.stack3.net/archives/1330

今回はAuto Layoutでのsubview配置について説明したいと思います。

Auto Layoutによる配置の基本的な考え方

従来のframeのCGRect指定やAutoresizingMaskのFlexibleWidth、FlexibleHeightに慣れている人は、頭の切替が必要だと思います。Auto LayoutによるSubview配置は以下のようにして考えます。

  • Superviewの上端 or 下端 or 左端 or 右端からの間隔(Space)
  • Superviewの水平方向中心、垂直方向中心に位置するかどうか
  • 他のViewとの相対位置。間隔、アライン合わせ、サイズ合わせなど

Documentを読むよりInterface Builderでいろいろ触ってみて理解するのが早いです。適当なViewControllerを作って、With XIB for user interfaceにチェックし、xibも生成するようにしてください。

f:id:eimei23:20121231124157p:plain

Auto Layoutを有効にするためにxibのFile Inspectorを開いてUse Autolayoutにチェックが入っていることを確認してください。最新のXcodeで作ったプロジェクトなら初期状態でチェックが入っているはずです。

f:id:eimei23:20121231175719p:plain

SuperViewの外枠からの間隔指定で配置

 f:id:eimei23:20121231124739p:plain

このようにViewの四隅にButtonを配置してみましょう。ボタンを選択するとSuperviewの外枠に向かって伸びる青いバーが表示されます。これをConstraintと呼びます。ConstraintとはSubview配置の制約を意味しています。

f:id:eimei23:20121231124854p:plain

左端に伸びるConstraintを選択した状態。

Constraintである青いバーの間隔は、画面回転した時も守られ、画面サイズが異なる端末でも守られます。実際にSimulatorで動かして画面回転してみましょう。各Buttonが四隅にくっついたままであることを確認できます。

f:id:eimei23:20121231125047p:plain

f:id:eimei23:20121231125056p:plain

SimulatorのデバイスをiPhone 3.5-inch、4.0-inch、iPadどれにしても同様の動作になることも確認してみてください。

InterfaceBuilderに戻って左上に配置したボタンを選択してSize Inspectorを見てみましょう。

f:id:eimei23:20121231190742p:plain

Constraintsのセクションに

  • Top Space to: Superview
  • Leading Space to: Superview

という項目があります。前者はSuperviewの上端からの間隔を固定するConstraint、後者はSuperviewの左端からの間隔を固定するConstraintです。それぞれButtonから上端へ伸びる青いバー、左端へ伸びる青いバーに対応しています。

次に右下に配置したボタンを選択してSize Inspectorを見てみましょう。

f:id:eimei23:20121231190842p:plain

Constraintsのセクションに

  • Bottom Space to: Superview
  • Trailing Space to: Superview

という項目があります。前者はSuperviewの下端からの間隔を固定するConstraint、後者はSuperviewは右端からの間隔を固定するConstraintです。それぞれButtonから下へ伸びる青いバー、右へ伸びる青いバーに対応しています。

まとめると、

  • Leading Space to Superviewは、左端間隔固定
  • Trailing Space to Superviewは、右端間隔固定
  • Top Space to Superviewは、上端間隔固定
  • Bottom Space to Superviewは、下端間隔固定

となります。LeadingとTrailingがちょっと覚えづらいかもしれません・・・

もう一度、左上のButtonを選択して、Size InspectorのConstrainsのセクションを見てみましょう。Button配置の際に表示される青い点線のガイドにしたがって配置した場合、Equals: Defaultになっていると思います。

その状態から右下の方に向けて少しドラッグしてみましょう。

f:id:eimei23:20121231125528p:plain

そうすると以下のようにEqualsが実際の間隔の値を表すようになります。

f:id:eimei23:20121231125542p:plain

Defaultの間隔は20pxです。もう一度、Buttonをドラッグして青い点線のガイドに合わせて配置するとEquals: Defaultに戻ります。

次に新しいButtonを以下のX:20 Y:100の位置に配置してください。

f:id:eimei23:20121231125618p:plain

位置はSize Inspactorで確認できます。

f:id:eimei23:20121231191013p:plain

Buttonを選択すると上と左に青いバーが端に向かって伸びています。Size InspectorのConstraintsにLeading Space to: SuperviewとTop Space to: Superviewがあるのを確認できます。(HeightやAlign BaselineというConstraintもありますが、今回は無視してください)

Simulatorを起動して画面を回転してみてください。新しいボタンは上端からと左端からの間隔を固定するはずです。

f:id:eimei23:20121231125910p:plain

f:id:eimei23:20121231125917p:plain

自分でConstraintを設定する

これまではButtonを配置すると、その位置から自動的にConstraintが決められてきました。Auto Layoutで表示する場合、Subviewに必ずConstraintが必要になります。そうしないとAuto Layoutのエンジンがどこに配置して良いか判断できないからです。Auto LayoutではConstraintが必須であるため、Subview配置と同時に強制的に何かしらのConstraintが設定されます。

ただ自動で決められたConstraintは都合が悪い場合もあります。さきほど追加したButtonをもう一度選択して見てみましょう。

f:id:eimei23:20121231125618p:plain

このように左端からの間隔を固定するようになっていますが、本当は右端からの間隔を固定したい場合があります。その場合は、

  • メニュー > Editor > Pin > Tailing Space to Superview

を選択します。そうするとButtonからSuperviewの右端に向かって伸びるバーが追加されます。Buttonから左端、右端へ伸びるバーが太くなっていることに注目してください。

f:id:eimei23:20121231130145p:plain

Size Inspectorを見るとTrailing Space to: Superviewが追加されているのがわかります。

f:id:eimei23:20121231130418p:plain

また今まであったLeading Space to: Superviewの左アイコンが紫から青色に変わっていることに注目してください。さらに今回追加したTailing Space to: Superviewも青色アイコンです。

このようにバーが太いConstraint、Size Inspectorでアイコンが青色のConstraintは自動で決められたConstraintではなく、ユーザーによって決められたものだということを示しています。これをUser Constraintと呼びます。User Constraintは削除が可能です。

Trailing Space to Superview(右端からの間隔固定)を追加したことによって、Leading Space to Superview(左端からの間隔固定)もUser Constraintになったのは、どちらか片方はなくてもAuto Layoutは成立するからです。今回は右端からの間隔を固定したいだけなので、Leading Space to Superviewは削除しましょう。

削除は以下のいずれかでできます。

  • 配置したボタンの選択 > 左に伸びているバーを選択 > Deleteキーを押す
  • Size InspectorのConraintsセクションからLeading Space to Superviewの歯車アイコンを押す > プルダウンメニューからDeleteを選択

これでButtonから右端に伸びるバーだけになりました。Simulatorを起動して画面を横に回転させましょう。右端からの間隔が固定されているはずです。

f:id:eimei23:20121231130723p:plain

このように自動で決められて都合が悪いConstraintは自分で設定することになります。

ちなみにこれを試している間に、下の2つのボタンのタイトルが表示されないというバグが発生しました・・・Interface Builderでは表示されているのですが、Simulatorで起動すると表示されない。もう一度、Buttonを再配置するなどしたら直りましたが・・・ちょっと怖いですね。原因が分かる人がいたら教えてください。

次回はInterface Builderを使ったAuto Layoutに関する操作について説明します。

その2へつづく